MySQL 에서 DDL을 실행할 때의 트랜잭션 처리 방식과 암묵적 커밋(Implicit Commit) 에 대한 이슈를 통해 정리한 글 입니다
MySQL 에서는 DDL이 실행되면 자동으로 커밋이 발생합니다.
이를 "암묵적 커밋 (Implicit Commit)" 이라고 부릅니다
예시
START TRANSACTION;
INSERT INTO user VALUES(1, '철수');
ALTER TABLE user ADD COLUMN email VARCHAR(255);
ROLLBACK;
결과
→ ALTER TABLE 이 실행되는 순간, 앞서 실행된 INSERT 도 함께 커밋됨 이후 ROLLBACK 은 무의미하게 됩니다
왜 이렇게 동작할까 ?
관련 문서 : MySQL 공식문서 - Implicit Commit
실무에서 DDL 을 실행하는 도중에 lock wait timeout exceeded 오류가 발생한 경우가 있습니다.
이는 해당 테이블의 메타데이터 락 (MDL)을 다른 트랜잭션이 쥐고 있어서 발생하는 문제 입니다.
실제로 일어난 흐름
ALTER TABLE 쿼리를 실행 중 lock wait timeout exceeded 에러 발생 SHOW FULL PROCESSLIST 로 확인해보니 Sleep 상태의 커넥션이 존재 KILL 하니 이후 DDL 실행이 정상적으로 처리됨 원인 분석
MDL_EXCLUSIVE 락을 요구함 SELECT 쿼리를 통해 MDL_SHARED 락을 잡고 있었다면 충돌 발생 KILL 명령으로 세션 종료 → MDL 해제 → 이후 쿼리 정상 실행 이후 알게된 것
SHOW PROCESSLIST + performance_schema.metadata_locks 로 누가 락을 가지고 있는지 확인performance_schema.threads 테이블 join)참고
IntelliJ 에서 한 콘솔에 여러 DDL 을 실행하면 일반적으로 하나의 커넥션에서 처리됩니다
Auto-commit 이 꺼져 있어도 DDL 은 내부적으로 자동 커밋되고, 커넥션이 새로 생성되지는 않습니다
SHOW FULL PROCESSLIST결과, 여러 Sleep 커넥션이 남지 않음이 확인되었습니다과거에 Sleep 커넥션이 다수 쌓였던 현상은 백그라운드 구조 동기화(Auto Sync), 여러 세션 열림, 실패한 트랜잭션이 커밋되지 않은 채 유지된 경우일 수 있습니다.
MDL 은 테이블, 컬럼, 인덱스 등 메타데이터에 대한 동시 접근을 제어하기 위한 락입니다.
메타데이터를 수정하거나 읽는 모든 쿼리는 이 락을 획득해야 합니다
종류
MDL_SHARED MDL_SHARED_READ , MDL_SHARED_WRITE 등으로 나뉘어 있습니다MDL_EXCLUSIVE Exclusive Lock 은 하나의 트랜잭션만 획득 가능한 LockExclusive Lock 은 테이블에 대해 어떠한 Lock 도 걸려있지 않아야 획득 가능합니다ALTER, DROP, RENAME 등 구조 변경 시 사용합니다.MDL_INTENTION Intention Lock 은 잠금을 걸기 전에 먼저 의도(intent)를 표시하며 다른 트랜잭션 과의 충돌을 방지하기 위해 InnoDB 에서 사용하는 잠금 메커니즘 입니다.특징: 트랜잭션 종료와 무관하게 커넥션이 열려 있으면 락이 유지됨
언제 걸리는 것 인가?
SELECT * FROM table → MDL_SHAREDALTER TABLE table ... → MDL_EXCLUSIVESHOW COLUMNS FROM table → MDL_SHAREDMySQL 의 InnoDB 엔진은 DML 시 내부적으로 다양한 레코드 수준의 락을 사용합니다
이들과 MDL 은 전혀 다른 레이어 입니다
종류
X (Exclusive Lock) UPDATE , DELETE 등에서 해당 ROW 를 다른 트랜잭션이 접근하지 못하게 막음 S (Shared Lock)SELECT ... LOCK IN SHARE MODE 에서 사용 IX / IS (Intention LockGap LockNext-Key Lock격리 수준과 락의 결정 방식
REPEATABLE READ 격리 수준에서는 기본적으로 Next-Key Lock 을 사용하여 팬텀 리드를 방지합니다 즉, 쿼리 결과가 정확히 유니크한 하나의 레코드일 경우에는 Gap Lock 대신 Record Lock만 획득합니다
MDL 과의 차이점
lock wait timeout 이 발생했다면 다른 커넥션이 해당 테이블에 MDL 락을 쥐고 있어서 생긴 현상일 가능성이 높다 REPEATABLE READ 격리 수준에서 범위 조회는 Gap + Record (Next-Key Lock) 를, 유니크 단건 조회는 Record Lock 만 획득한다SHOW PROCESSLIST, performance_schema.metadata_locks , performance_schema.threads 를 통해 커넥션 및 실행 시점, 락 상태를 확인하면 원인 추적이 수월하다 참고