FLUSH TABLES WITH READ LOCK
명령으로 획득 가능SELECT
를 제외한 DDL 문장이나 DML이 대기하게 된다.글로벌 락은 보통 MyISAM이나 MEMORY 스토리지 엔진에서 일관된 백업을 받아야 할 때 사용했다. 하지만 8.0 버전부터 InnoDB의 사용이 일반화 되었다. 트랜잭션의 도움을 받을 수 있어서 데이터의 모든 변경을 멈출 필요가 없어졌다. 그래서 가벼운 글로벌 락의 필요성이 생겼고 MySQL 8.0부터는 Xtrabackup이나 Enterprise Backup 같은 백업 툴들의 안정적인 실행을 위해 백업 락이 도입 됐다.
LOCK INSTANCE FOR BACKUP;
-- // 백업 실행
UNLOCK INSTANCE;
LOCK TABLES table_name [ READ/WRITE ]
GET_LOCK()
함수로 임의의 문자열에 대해 잠금을 설정할 수 있다.
-- // "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();
RENAME TABLE tab_a TO tab_b
같은 명령어로 획득할 수 있다.RENAME
명령어의 경우 원본 이름과 변경 이름 모두 한 번에 잠금을 설정한다.rank
라는 테이블의 데이터를 rank_backup
으로 백업하고, 새로 만들어진 랭킹 테이블인 rank_new
를 서비스용으로 대체하고자 하는 경우rank
의 데이터를 rank_backup
으로 백업하였다.rank_new
를 서비스용으로 대체해야 한다.RENAME TABLE rank TO rank_backup;
RENAME TABLE rank_new TO rank;
RENAME
명령을 따로 실행하면 아주 짧은 시간 동안 rank
테이블이 존재하지 않게 되며 그 때 실행되는 쿼리는 Table not found ‘rank’
오류가 발생하게 된다.RENAME TABLE rank TO rank_backup, rank_new TO rank;
rank
라는 이름에 잠금이 걸린 상태에서 이름을 한 번에 바꾸기 때문access_log
라는 테이블에는 INSERT
만 실행된다.Online DDL: DDL 작업을 수행할 때 해당 테이블에 잠금을 수행하거나 다른 트랜잭션이 해당 테이블에 접근하지 못하게 하는 것을 필요하지 않게 하는 기능이다.
access_log_new
) 최근 데이터까지는 pk 범위 별로 여러 스레드로 빠르게 복사한다.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;
RENAME
명령으로 운영 환경에서 중단 없이 실행할 수 있다.
-- 트랜잭션 시작. (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;