TIL

5.2 MySQL 엔진에서의 잠금

5.2.1 글로벌 락

글로벌 락은 보통 MyISAM이나 MEMORY 스토리지 엔진에서 일관된 백업을 받아야 할 때 사용했다. 하지만 8.0 버전부터 InnoDB의 사용이 일반화 되었다. 트랜잭션의 도움을 받을 수 있어서 데이터의 모든 변경을 멈출 필요가 없어졌다. 그래서 가벼운 글로벌 락의 필요성이 생겼고 MySQL 8.0부터는 Xtrabackup이나 Enterprise Backup 같은 백업 툴들의 안정적인 실행을 위해 백업 락이 도입 됐다.

백업 락

LOCK INSTANCE FOR BACKUP;
-- // 백업 실행
UNLOCK INSTANCE;

5.2.2 테이블 락

5.2.3 네임드 락

-- // "mylock"이라는 문자열에 대해 잠금을 획득한다.
-- // 이미 잠금을 사용 중이라면 2초 동안 대기한다. (2초 후 자동 잠금 해제)
SELECT GET_LOCK('mylock', 2);

-- // "mylock"이라는 문자열에 대해 잠금이 설정돼 있는지 확인
SELECT IS_FREE_LOCK('mylock');

-- // "mylock"이라는 문자열에 대해 획득했던 잠금을 반납
SELECT RELEASE_LOCK('mylock');
SELECT GET_LOCK('mylock_1', 2);
SELECT GET_LOCK('mylock_2', 2);

SELECT RELEASE_AL_LOCKS();

5.2.4 메타데이터 락

활용 예1

RENAME TABLE rank TO rank_backup;
RENAME TABLE rank_new TO rank;
RENAME TABLE rank TO rank_backup, rank_new TO rank;

활용 예2

Online DDL: DDL 작업을 수행할 때 해당 테이블에 잠금을 수행하거나 다른 트랜잭션이 해당 테이블에 접근하지 못하게 하는 것을 필요하지 않게 하는 기능이다.

INSERT INTO access_log_new SELECT * FROM access_log WHERE id>=0 AND ID<10000;
INSERT INTO access_log_new SELECT * FROM access_log WHERE id>=10000 AND ID<20000;
INSERT INTO access_log_new SELECT * FROM access_log WHERE id>=20000 AND ID<30000;
INSERT INTO access_log_new SELECT * FROM access_log WHERE id>=30000;
-- 트랜잭션 시작. (BEGIN이나 START TRANSACTION으로 하면 안 됨)
SET autocommit=0;

-- 작업 대상 테이블 2개에 쓰기 락 획득
LOCK TABLES access_log WRITE, access_log_new WRITE;

-- 남은 데이터 복사
SELECT MAX(id) as @MAX_ID FROM access_log;
INSERT INTO access_log_new SELECT * FROM access_log WHERE id>@MAX_ID;;
COMMIT;

-- 복사가 완료되면 구조가 변경된 새 테이블을 서비스로 투입
RENAME TABLE access_log TO access_log_old, access_log_new TO access_log;
UNLOCK TABLES;

-- 불필요한 테이블 삭제
DROP TABLE access_log_old;