MariaDB / Query / EVENT / 만들기, 수정하기, 삭제하기

MariaDB EVENT는 데이터베이스 안의 SQL 작업을 한 번 또는 일정 간격으로 실행하는 예약 객체입니다. CREATE EVENT로 만들고 ALTER EVENT로 일정·본문·활성 상태를 바꾸며 DROP EVENT로 삭제합니다. 이벤트 자체가 활성 상태여도 서버의 Event Scheduler가 켜져 있어야 실행되므로 두 상태를 따로 확인해야 합니다.

권한·서버 스케줄러·시간대 먼저 확인

이벤트 생성·수정·삭제에는 해당 데이터베이스의 EVENT 권한이 필요합니다. 실행 시에는 이벤트의 DEFINER 계정이 본문 작업에 필요한 테이블 권한을 가져야 합니다. 서버 스케줄러의 전역 설정은 별도의 관리자 권한이 필요하며 이벤트 한 개의 상태 변경과 다릅니다. 이벤트 개요에서 권한과 실행 조건을 확인할 수 있습니다.

SELECT @@global.event_scheduler AS scheduler_status,
       @@session.time_zone AS session_time_zone,
       CURRENT_TIMESTAMP AS session_now;
SELECT EVENT_SCHEMA, EVENT_NAME, STATUS
FROM information_schema.EVENTS
WHERE STATUS = 'ENABLED' ORDER BY EVENT_SCHEMA, EVENT_NAME;

스케줄러 값은 ON·OFF·DISABLED를 구분합니다. OFF는 관리자가 동적으로 켤 수 있지만 DISABLED는 시작 설정에 의해 비활성화되어 실행 중 ON으로 바꿀 수 없는 상태입니다. 메타데이터 조회에서 보이는 이벤트 범위는 권한에 따라 다릅니다. 전역 스케줄러를 켜면 다른 활성 이벤트도 실행될 수 있으므로 관리자에게 서버 전체 상태를 확인받고 작업 범위를 정합니다. 운영 서버를 실습용으로 사용하지 않습니다.

이 글의 실습은 learning 데이터베이스와 별도 MariaDB 시험 서버를 전제로 합니다. 이후 절차는 같은 접속에서 진행하고 UTC 시간대로 일정을 지정합니다. 이름이 같은 실습 객체가 있으면 다른 이름을 사용합니다. 생성 직전의 세션 시간대와 SQL 모드가 이벤트 정의에 영향을 주므로 운영 시각은 명시적으로 관리하세요.

먼저 비활성 상태로 이벤트 생성

USE learning;
SET SESSION time_zone = '+00:00';
CREATE TABLE event_log_demo (
    id INT AUTO_INCREMENT PRIMARY KEY,
    marker VARCHAR(20) NOT NULL,
    executed_at DATETIME NOT NULL
) ENGINE=InnoDB;
CREATE EVENT learning.event_tick_demo
ON SCHEDULE EVERY 1 MINUTE
STARTS CURRENT_TIMESTAMP + INTERVAL 1 MINUTE
ON COMPLETION PRESERVE
DISABLE
DO INSERT INTO learning.event_log_demo(marker, executed_at)
   VALUES ('A', CURRENT_TIMESTAMP);

event_tick_demo는 1분 간격의 반복 이벤트이지만 DISABLE로 만들었으므로 아직 행을 넣지 않습니다. CREATE EVENT 문법에서 EVERY는 반복 간격, STARTS는 시작 기준, DO는 실행할 SQL입니다. DO가 단일 문장이므로 이 예제에는 DELIMITER 변경이 필요하지 않습니다. 여러 문장으로 구성한다면 클라이언트 구분자와 BEGIN ... END를 함께 처리해야 합니다.

SHOW CREATE EVENT learning.event_tick_demo;
SELECT EVENT_NAME, STATUS, TIME_ZONE, INTERVAL_VALUE, INTERVAL_FIELD,
       STARTS, LAST_EXECUTED, DEFINER
FROM information_schema.EVENTS
WHERE EVENT_SCHEMA = 'learning' AND EVENT_NAME = 'event_tick_demo';
SELECT COUNT(*) AS log_rows FROM learning.event_log_demo;

STATUS는 DISABLED, 시간대는 +00:00, 간격은 1 MINUTE이고 실행 전 LAST_EXECUTED는 NULL, 로그 행 수는 0이어야 합니다. SHOW CREATE EVENT로 실제 본문·일정·DEFINER를 확인하고 변경 전 정의를 백업합니다. 같은 이름을 무조건 CREATE OR REPLACE로 덮어쓰면 기존 정의를 잃을 수 있으므로 필요한 변경을 ALTER로 지정합니다.

스케줄러와 이벤트를 활성화하고 실행 확인

시험 서버의 스케줄러가 OFF이고 실행 대상 확인이 끝난 경우에만 관리자가 다음 전역 명령을 실행합니다. 이미 ON이면 다시 설정할 필요가 없습니다. 이 명령이 설정 파일을 영구 수정하는 것은 아니며 재시작 뒤 값은 서버의 실제 시작 설정에 따릅니다.

SET GLOBAL event_scheduler = ON;

재시작 후에도 필요하면 실제로 읽는 서버 옵션 파일의 서버 그룹에 아래와 같이 설정합니다. 배포판별 파일명을 추정해 새 파일을 만들기보다 사용 중인 옵션 파일·기존 설정을 확인하고 백업한 뒤 승인된 점검 시간에 재시작합니다. 클러스터·복제 환경에서는 어느 서버에서 이벤트를 실행할지도 별도로 정해야 합니다.

[mariadb]
event_scheduler=ON

일정 검토가 끝났다면 이벤트의 시작을 현재로부터 5초 뒤로 다시 잡고 활성화합니다. 기존 STARTS 시각을 그대로 둔 채 나중에 ENABLE하면 다음 실행 시점이 원하는 “지금부터 5초 뒤”가 아닐 수 있으므로 이 실습에서는 둘을 함께 지정합니다.

ALTER EVENT learning.event_tick_demo
ON SCHEDULE EVERY 1 MINUTE
STARTS CURRENT_TIMESTAMP + INTERVAL 5 SECOND
ENABLE;
SELECT id, marker, executed_at FROM learning.event_log_demo ORDER BY id;
SELECT EVENT_NAME, STATUS, LAST_EXECUTED
FROM information_schema.EVENTS
WHERE EVENT_SCHEMA = 'learning' AND EVENT_NAME = 'event_tick_demo';

시작 시간이 지나면 A 행이 생기고 이후 약 1분 간격으로 추가됩니다. 즉시 조회하면 아직 0행일 수 있으므로 스케줄러·현재 시각·STARTS를 함께 확인합니다. 실시간 정밀 타이머가 아니어서 부하 등에 따라 지연될 수 있습니다. EVENTS의 LAST_EXECUTED는 최근 실행 시각이며 업무가 성공했다는 보증은 아닙니다. 결과 테이블·처리 건수·서버 오류 로그도 함께 확인해야 합니다. SELECT 결과를 호출자 화면으로 반환받는 용도로 이벤트를 사용하지 않습니다.

일정과 본문을 수정할 때는 중지 후 검토

아래는 이벤트를 먼저 비활성화하고 반복 간격을 2분, 기록 값을 B로 바꾸는 예제입니다. 이 변경은 과거의 A 행을 B로 수정하지 않습니다. 일정이나 본문만 바꾸는 ALTER가 어떤 속성을 유지하는지도 변경 후 정의에서 확인하세요.

ALTER EVENT learning.event_tick_demo DISABLE;
ALTER EVENT learning.event_tick_demo
ON SCHEDULE EVERY 2 MINUTE
STARTS CURRENT_TIMESTAMP + INTERVAL 1 MINUTE
DO INSERT INTO learning.event_log_demo(marker, executed_at)
   VALUES ('B', CURRENT_TIMESTAMP);
SHOW CREATE EVENT learning.event_tick_demo;

검토가 끝난 뒤 다시 활성화하려면 다음과 같이 시작 시각과 ENABLE을 지정합니다. 시작 후 앞 절의 조회 SQL로 새 B 행과 기존 A 행이 구분되는지 확인합니다. 이벤트 정의 변경은 이미 실행 중인 작업을 자동 취소하거나 작업 결과를 롤백하는 기능이 아니므로, 긴 작업은 실행 상태와 별도의 중단·중복 제어도 설계해야 합니다.

ALTER EVENT learning.event_tick_demo
ON SCHEDULE EVERY 2 MINUTE
STARTS CURRENT_TIMESTAMP + INTERVAL 5 SECOND
ENABLE;

ALTER EVENT 문서에 따라 수정 계정과 DEFINER의 변화도 확인합니다. 실행 시간이 간격보다 긴 작업은 중첩될 수 있으므로 유일 키·작업 상태·적절한 잠금 등으로 중복 실행을 처리합니다. “간격마다 정확히 한 번 성공한다”는 전제로 금전·재고 등 중요한 데이터를 무조건 증감시키지 않습니다.

한 번만 실행하는 이벤트와 보존 여부

반복 실습을 중지하고 AT로 일회성 이벤트를 만들 수 있습니다. ON COMPLETION PRESERVE는 완료한 정의를 확인용으로 남깁니다. 보존하지 않는 기본 동작에서는 종료한 이벤트가 제거될 수 있어 이벤트 목록에서 보이지 않는 이유도 구분해야 합니다.

ALTER EVENT learning.event_tick_demo DISABLE;
CREATE EVENT learning.event_once_demo
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 5 SECOND
ON COMPLETION PRESERVE
ENABLE
DO INSERT INTO learning.event_log_demo(marker, executed_at)
   VALUES ('once', CURRENT_TIMESTAMP);

예약 시각 뒤에는 once 행이 한 번 기록되고, 보존된 일회성 이벤트의 상태는 비활성으로 확인할 수 있습니다. 과거 시각과 ON COMPLETION NOT PRESERVE를 조합하면 생성 직후 제거될 수도 있으므로, 고정된 오래전 날짜를 복사해 쓰지 말고 현재 시간과 시간대를 확인하세요. 서버 중지·실패·권한 오류가 있어도 외부 업무까지 자동으로 복구되거나 누락 작업이 원하는 방식으로 재시도되는 것은 아닙니다.

정의 백업 후 이벤트 삭제와 실습 종료

삭제 전에 올바른 데이터베이스·이벤트 이름과 SHOW CREATE EVENT 백업을 확인합니다. DROP EVENT는 예약 정의를 지우며 기존 로그 행은 남습니다. 아래는 이 글에서 만든 두 이벤트만 정리합니다.

ALTER EVENT learning.event_tick_demo DISABLE;
SHOW CREATE EVENT learning.event_tick_demo;
SHOW CREATE EVENT learning.event_once_demo;
DROP EVENT learning.event_tick_demo;
DROP EVENT learning.event_once_demo;
SELECT COUNT(*) AS remaining_demo_events FROM information_schema.EVENTS
WHERE EVENT_SCHEMA = 'learning'
  AND EVENT_NAME IN ('event_tick_demo','event_once_demo');
SELECT marker, COUNT(*) AS log_rows
FROM learning.event_log_demo GROUP BY marker ORDER BY marker;

남은 실습 이벤트 수는 0이고 실행되어 저장된 A·B·once 기록은 유지됩니다. 기존에 ON이던 서버 스케줄러를 실습 종료만을 이유로 끄지 않습니다. 시험용으로 OFF에서 ON으로 바꿨고 다른 작업이 없음을 확인했다면 관리자와 원래 설정으로 복구합니다. 이벤트 삭제나 DISABLE도 이미 실행 중인 문장을 즉시 중단한다고 가정하지 않으며, 실제 실행 상태를 확인한 뒤 후속 정리를 진행합니다.