14.2.6 InnoDB 레코드 격차 및 넥스트 키 잠금
InnoDB
의 레코드 수준 잠금은 레코드 잠금 격차 록, 넥스트 키 잠금 등의 여러 종류가 있습니다. 공유 잠금 단독 잠금 및 인텐션 잠금 내용은 섹션 14.2.3 "InnoDB 잠금 모드" 를 참조하십시오.
레코드 잠금 : 이것은 인덱스 레코드 잠금입니다.
갭 잠금 : 이것은 인덱스 레코드 사이에 격차 잠금 또는 초기 인덱스 레코드 앞이나 뒤에 인덱스 레코드 뒤에있는 갭 잠금입니다.
넥스트 키로 크 : 이것은 인덱스 레코드에 대한 레코드 잠금과 그 인덱스 레코드 앞에있는 갭에 대한 갭 잠금을 조합 한 것입니다.
레코드 잠금
레코드 잠금은 테이블에 인덱스가 정의되어 있지 않아도 반드시 인덱스 레코드가 잠겨 있습니다. 이런 경우는 InnoDB
에 의해 숨겨진 클러스터 된 인덱스가 생성되고이 인덱스를 사용하여 레코드 잠금이 이루어집니다. 섹션 14.2.13.2 "클러스터 인덱스와 보조 인덱스" 를 참조하십시오.
넥스트 키 잠금
기본적으로 InnoDB
는 REPEATABLE READ
트랜잭션 격리 수준에서 작동하고 innodb_locks_unsafe_for_binlog
시스템 변수는 비활성화되어 있습니다. 이 경우 InnoDB
는 넥스트 키 잠금을 사용하여 검색 및 인덱스 스캔을하기 위해 팬텀 행의 발생을 방지 할 수 있습니다 ( 섹션 14.2.7 "넥스트 키로 크에 의한 팬텀 문제 해결" 참조).
넥스트 키 잠금은 인덱스 행 잠금 및 갭 잠금을 조합 한 것입니다. InnoDB
는 테이블 인덱스를 검색 또는 스캔 할 때 생성 된 인덱스 레코드에 공유 락 또는 배타 락을 설정하는 방법으로 행 수준 잠금을 실행합니다. 따라서 행 레벨 락은 실제로 인덱스 레코드 잠금입니다. 게다가 어느 인덱스 레코드에 넥스트 키 잠금은 인덱스 레코드 앞의 '갭'에도 영향을받습니다. 즉, 넥스트 키 잠금은 인덱스 레코드 잠금과 그 인덱스 레코드의 전의 갭에 대한 갭 잠금을 조합 한 것입니다. 세션이 인덱스의 레코드 R
에 공유 락 또는 배타 락을 가지고 있다면, 다른 세션이 인덱스 순서로 R
의 직전에있는 갭에 새로운 인덱스 레코드를 삽입 할 수 없습니다.
있는 인덱스 값 10,11,13,20가 포함되어 있다고합니다. 이 인덱스는 다음과 거리를 커버하는 넥스트 키 잠금을 사용 될 수 있습니다. 여기서, (
나 )
는 간격의 끝이 포함되지 않는 것을 나타내며 [
나 ]
는 간격의 끝이 포함 된 것을 나타냅니다.
(negative infinity 10] (10, 11] (11, 13] (13, 20] (20, positive infinity)
마지막 간격은 넥스트 키 잠금은 인덱스의 최대 값보다 큰 갭 및 인덱스의 실제 값보다 큰 값을 가지는 "최소 상한"의사 레코드가 잠겨 있습니다. 최소 한도는 실제 인덱스 레코드가 아니기 때문에 사실상이 넥스트 키 자물쇠로 잠겨은 최대 인덱스 값의 뒤에있는 갭뿐입니다.
갭 잠금
이전 섹션에서 설명한 넥스트 키 록의 예는 갭의 범위가 단일 인덱스 값 여러 인덱스 값 또는 비우는 경우도 있다는 것을 보여줍니다.
고유 인덱스를 사용하여 고유 한 행을 검색하여 행을 잠그는 문은 갭 잠금은 필요하지 않습니다. (여기에는 검색 조건에 여러 컬럼의 고유 인덱스의 일부 컬럼 만 포함 된 케이스는 포함되지 않습니다.이 경우에는 갭 잠금이 발생합니다.) 예를 들어, id
컬럼에 고유 한 인덱스 이 설정되어있는 경우 다음 문에서 사용되는 것은 id
값이 100 행의 인덱스 레코드 잠금 만이 다른 세션이 레코드 앞에있는 갭에 행을 삽입할지 여부는 문제 는 없습니다.
SELECT * FROM child WHERE id = 100;
id
인덱스가 설정되어 있지 않거나 고유하지 않은 인덱스가 설정되어 있거나하면이 문 앞의 격차가 잠겨 있습니다.
INSERT
작업은 행 삽입 전에 삽입 인텐션 갭 잠금라는 일종의 갭 잠금이 설정됩니다. 이 잠금은 같은 인덱스 갭에 삽입하는 여러 트랜잭션은 그 차이의 동일한 위치에 삽입해야 서로 기다릴 필요가 없도록 의도적으로 삽입하는 것을 보여줍니다. 값이 4와 7의 인덱스 레코드가 존재한다고 가정합니다. 각 값 5와 6의 삽입을 시도 별도의 트랜잭션은 삽입 된 행의 배타 락을 취득하기 전에 삽입 인텐션 잠금을 사용하여 4와 7 사이의 갭을 잠그는하지만 행 충돌이 발생하지 않기 때문에 서로 차단되지 않습니다. 인텐션 잠금에 대한 자세한 내용은 섹션 14.2.3 "InnoDB 잠금 모드" 를 참조하십시오.
다양한 트랜잭션에 의해 격차에 충돌 잠금을 유지할 수있는 것도 여기서 주목해야 할 점입니다. 예를 들어, 트랜잭션 A 격차에 공유 갭 잠금 (갭 S 잠금)을 저장할 수있는 반면, 트랜잭션 B는 같은 간격에 독점적 갭 잠금 (갭 X 잠금)를 보유하고있다.경쟁 격차 잠금이 허용되는 이유는 레코드를 인덱스에서 제거 될 경우 다양한 트랜잭션이 기록에 보관 된 갭 잠금을 병합해야하기 때문입니다.
InnoDB
의 갭 잠금은 "단순히 억제」입니다. 즉, 다른 트랜잭션에 의한 격차의 삽입이 정지 될뿐입니다. 따라서 갭 X 잠금의 효과는 차이 S 잠금과 같습니다.
갭 잠금 해제
갭 잠금은 명시 적으로 비활성화 할 수 있습니다. 이것은 트랜잭션 격리 수준을 READ COMMITTED
로 변경하거나 innodb_locks_unsafe_for_binlog
시스템 변수 (현재는 비추천입니다)를 사용하는 경우 발생합니다. 이러한 상황에서는 갭 잠금은 검색 및 인덱스 스캔시 비활성화 된 외래 키 제약 조건 검사 및 중복 키 확인시에만 사용됩니다.
READ COMMITTED
격리 수준을 사용하거나 innodb_locks_unsafe_for_binlog
를 사용했을 경우의 효과는 그 밖에도 있습니다. 일치하지 않는 행의 레코드 잠금은 MySQL에 의한 WHERE
조건의 평가가 완료되면 해제됩니다. UPDATE
문의 경우, InnoDB
는 마지막으로 커밋 된 버전이 MySQL에 반환하도록 "반 일관성」읽기를 실행합니다. 이렇게하면 MySQL은 행이 UPDATE
의 WHERE
조건에 일치하는지 여부를 확인할 수 있습니다.