information_schema
데이터베이스에 존재하는 INNODB_TRX
, INNODB_LOCKS
, INNODB_LOCK_WAITS
테이블을 조인해서 조회해서 확인할 수 있다.perfornamce_schema
데이터베이스의 data_locks
와 data_lock_waits
테이블로 대체되고 있다.AUTO_INCREMENT
칼럼 속성을 만족하기 위한 자동 증가 숫자 값을 채번하기 위해 InnoDB에서 제공하는 테이블 수준의 잠금을 의미한다.
INSERT
되어도 중복되지 않는 순서대로의 pk를 얻을 수 있다.INSERT
, REPLACE
에서만 걸리는 잠금AUTO_INCREMENT
값을 가져오는 순간만 락이 걸렸다가 즉시 해제된다.MySQL 5.1부터는 innodb_autoinc_lock_mode
변수를 이용해 자동 증가 락의 작동 방식을 변경할 수 있다.
=0
INSERT
문에 자동증가 락 사용=1
INSERT
시에는 자동 증가 락 대신 훨씬 가볍고 빠른 래치(뮤텍스)를 이용해 처리한다.INSERT … SELECT
와 같이 건수 예측이 불가능할 땐 자동 증가 락을 사용한다.
INSERT
시 InnoDB는 여러 개의 자동 증가 값을 한 번에 할당 받아 사용하고 남는 자동 증가 값이 있으면 폐기한다.INSERT
쿼리가 오래 걸리면 다른 세션의 INSERT
는 대기한다.INSERT
문장으로 삽입되는 레코드는 연속된 증가 값을 가지게 되어 연속 모드라고도 한다.=2
INSERT
문장으로 삽입 되더라도 연속된 증가 값을 보장하지 않아 인터리빙 모드라고도 한다.INSERT
쿼리가 대기하지 않아도 된다.
하지만 MySQL 8.0부터는 바이너리 로그 포맷의 기본값이 ROW 포맷이 되었고
innodb_autoinc_lock_mode
의 기본값은 2가 되었다.
다시 언급하지만 InnoDB의 잠금은 레코드 자체가 아닌 인덱스에 잠금을 건다. 즉 변경할 레코드를 찾기 위해 검색한 인덱스 모두 락을 걸게 된다.
emplyees
테이블의 first_name
컬럼에만 인덱스가 걸려 있고 last_name
컬럼에는 인덱스가 없다.UPDATE employees SET hire_date=NOW()
WHERE first_name='Georgi' AND last_name='Klassen';
first_name=’Georgi’
인 사람이 100명이고 last_name=’Klassen’
까지 만족하는 사람은 1명이다.테이블에 인덱스가 하나도 없다면 테이블 풀 스캔을 하면서 레코드를 찾기 때문에 모든 레코드를 잠그게 된다. 이런 현상이 발생하기 때문에 InnoDB에선 인덱스 설계가 매우 중요하다.
emp_no=10001
인 레코드에 3개의 UPDATE
쿼리가 들어오고 아직 커밋되지 않은 상황을 살펴보자.SHOW PROCESSLIST;
id | Time | State | Info |
---|---|---|---|
17 | 607 | NULL | |
18 | 22 | updating | UPDATE employees … WHERE emp_no=10001 |
19 | 21 | updating | NULL |
UPDATE
쿼리(17)는 커밋 되지 않았지만 명령을 실행 했고 나머지 두 쿼리는 명령을 실행하지 못하고 대기하는 것을 확인할 수 있다.performance_shcema
의 data_locks
테이블과 data_lock_waits
테이블을 조인해서 잠금 대기 순서를 확인할 수 있다.SELECT
r.trx_id waiting_trx_id,
r. trx_mysql_thread_id waiting_thread, r.trx_query walting_query,
b.trx_id blocking_trx_id,
b.trx_mysql_thread_id blocking_thread,
b.trx_query blocking_query
FROM performance_schema.data_lock waits w
INNER JOIN information_schema.innodb_trx b
ON b.trx_id = w.blocking_engine_transaction_id
INNER JOIN information_schema.innodb_trx r
ON r.trx_id = w.requesting_engine_transaction_id;
waiting_trx_id | waiting_thread | waiting_query | blocking_trx_id | blocking_thread | blocking_query |
---|---|---|---|---|---|
11990 | 19 | UPDATE.. | 11989 | 18 | UPDATE.. |
11990 | 19 | UPDATE.. | 11984 | 17 | NULL |
11989 | 18 | UPDATE.. | 11984 | 17 | NULL |
performance_schema
의 data_locks
테이블의 모든 컬럼을 보면 된다.KILL 17;
명령어를 실행 시키면 된다.