mysql의 격리 수준은 어떻게 구현됩니까?

王林
풀어 주다: 2020-06-28 09:35:53
원래의
2839명이 탐색했습니다.

mysql 격리 수준 구현 방법: 격리 수준이 커밋되지 않은 읽기인 경우 모든 읽기가 잠기지 않으며, 읽은 데이터는 최신 데이터이며, 모든 쓰기는 쓰기 후 행 수준 잠금으로 추가됩니다. , 풀어 주다. 격리 수준이 직렬화이면 읽기와 쓰기가 모두 잠깁니다.

mysql의 격리 수준은 어떻게 구현됩니까?

격리 수준

(권장 튜토리얼: mysql tutorial)

데이터베이스 트랜잭션에는 낮은 수준부터 높은 수준까지 4가지 격리 수준이 있으며, 커밋되지 않은 읽기(커밋되지 않은 읽기), 커밋된 읽기(읽기)가 있습니다. 제출), 반복 읽기(반복 읽기), 직렬화 가능(직렬화 가능), 이 네 가지 수준은 더티 읽기, 반복 불가능 읽기 및 팬텀 읽기 문제를 하나씩 해결할 수 있습니다.

격리 수준 구현:

커밋되지 않은 읽기(RU: read-uncommitted):

RU 수준에서 트랜잭션이 읽은 모든 데이터는 최신 데이터이며, 이는 트랜잭션이 커밋된 후의 데이터일 수 있습니다. 또는 트랜잭션 실행 중 데이터일 수도 있습니다(롤백될 수 있음).

격리 수준이 RU인 경우:

  • 모든 읽기가 잠기지 않고 읽은 데이터가 최신 데이터이며 성능이 최고입니다.

  • 모든 쓰기는 행 수준에서 잠기고 쓰기 후에 해제됩니다.

읽기 커밋(RC: 읽기 커밋):

MVCC 기술을 사용하여 각 행에 숨겨진 필드를 추가합니다(DB_TRX_ID: 행을 수정한 마지막 트랜잭션의 ID, DB_ROLL_PTR: 실행 취소 로그를 가리킴) 현재 행 로그, DB_ROW_ID: 행 식별, DELETE_BIT: 삭제 플래그), 잠금 없는 읽기 작업을 구현합니다.

격리 수준이 RC인 경우:

  • 쓰기 작업: 행 수준 잠금을 추가합니다. 트랜잭션이 시작되면 UNDO 로그에 수정 레코드가 기록되고, 데이터 행의 숨겨진 열 DATA_POLL_PTR에는 해당 행의 UNDO 레코드에 대한 포인터가 저장됩니다.

  • 읽기 작업: 잠금이 없습니다. 읽을 때 행이 다른 트랜잭션에 의해 잠겨 있으면 숨겨진 열 DATA_POLL_PTR 포인터를 따라 이전의 유효한 기록 레코드를 찾습니다(유효한 레코드: 이 레코드는 현재 트랜잭션에 표시되며 DELETE_BIT=0).

반복 읽기(RR: 반복 읽기):

MVCC 기술을 사용하여 잠금 없는 읽기 작업을 구현합니다.

격리 수준이 RR인 경우:

  • 쓰기 작업: 행 수준 잠금을 추가합니다. 트랜잭션이 시작된 후 UNDO 로그에 수정 레코드가 기록되고 데이터 행의 숨겨진 열 DATA_POLL_PTR에는 해당 행의 UNDO 레코드에 대한 포인터가 저장됩니다.

  • 읽기 작업: 잠금이 없습니다. 읽을 때 행이 다른 트랜잭션에 의해 잠겨 있으면 숨겨진 열 DATA_POLL_PTR 포인터를 따라 이전의 유효한 기록 레코드를 찾습니다(유효한 레코드: 이 레코드는 현재 트랜잭션에 표시되며 DELETE_BIT=0).

위에서 알 수 있듯이 실제로 RC 및 RR 수준의 작업은 기본적으로 동일하지만 차이점은 현재 트랜잭션에 대한 행 레코드의 가시성(가시성: 즉, 행 레코드의 버전이 이 트랜잭션에 표시됩니다.) 데이터의 RC 수준 가시성은 데이터의 최신 기록이고, 데이터의 RR 기본 가시성은 트랜잭션 시작 시 데이터의 기록입니다.

(1) 행 레코드 가시성(read_view) 구현

innodb에서는 트랜잭션 생성 시 현재 시스템의 활성 트랜잭션 목록에 대한 복사본(read_view)이 생성되어 모든 것을 저장하는 트랜잭션입니다. 현재 트랜잭션 시작 시 아직 커밋되지 않은 트랜잭션의 값은 현재 트랜잭션에 표시되지 않습니다.

read_view에는 두 가지 키 값 ​​​​up_limit_id(현재 커밋되지 않은 트랜잭션의 최소 버전 번호는 -1, up_limit_id 이전 트랜잭션이 제출되었으며 up_limit_id 이후 트랜잭션은 제출될 수 있지만 아직 제출되지 않을 수 있음) 및 low_limit_id가 있습니다. (현재 시스템은 아직 제출하지 않았습니다. 할당된 다음 트랜잭션 ID는 지금까지 발생한 트랜잭션 ID의 최대값입니다. 참고: low_limit_id는 가장 큰 활성 트랜잭션의 ID가 아닙니다. )

참고: 현재 트랜잭션과 커밋되는 트랜잭션이 read_view에 없습니다.

(2) RC 수준이든 RR 수준이든 행 레코드의 가시성을 판단하는 논리는 동일합니다.

트랜잭션이 실행 취소 시 행 레코드를 읽을 때 행 레코드의 버전 번호(DB_TRX_ID)가 read_view와 비교됩니다.

1. DB_TRX_ID가 up_limit_id보다 작으면 해당 행 레코드를 읽은 것입니다. 현재 트랜잭션이 시작되고 DELETE_BIT=0이면 현재 트랜잭션에 행 레코드가 표시됩니다.

2. DB_TRX_ID가 low_limit_id보다 크다면 해당 트랜잭션이 생성된 이후 해당 행이 기록되는 트랜잭션이 시작되었음을 의미하므로 해당 행 레코드의 현재 값이 표시되지 않습니다.

3. up_limit_id

4. 위의 판단이 보이지 않으면 Undo에서 해당 행의 이전 행 기록을 읽고 계속 판단합니다.

RC 수준의 명령문 수준 스냅샷과 RR 수준의 트랜잭션 수준 스냅샷의 차이는 실제로 read_view 생성 시점에 따라 구현됩니다.

RC 수준에서 명령문을 실행하면 원래 read_view가 먼저 닫히고 새 read_view가 다시 생성됩니다. RR 수준 read_view는 트랜잭션 시작 시에만 생성됩니다. 따라서 RU 레벨은 매번 최신 데이터를 가져오고, RR 레벨은 트랜잭션 시작 시 데이터를 가져옵니다.

(3) 주목할 점: 위의 가시성 판단에서 논리는 동일하지만 실제 의미에 차이가 있습니다.

두 번째 단계에서는 RC 수준에 대해 low_limit_id 최대 거래입니다. 구문 실행 시 발생한 ID + 1 구문 실행 시 low_limit_id보다 큰 트랜잭션은 없으므로 low_limit_id보다 큰 트랜잭션은 보이지 않는다고 볼 수 있다.

RR 수준의 경우 low_limit_id는 현재 트랜잭션 시작 시 발생한 가장 큰 트랜잭션 + 1입니다(현재 트랜잭션의 ID + 1로도 간주할 수 있습니다. 현재 트랜잭션이 생성될 때 id가 현재 트랜잭션의 최대값), 이는 low_limit_id보다 큽니다. 트랜잭션 표현은 트랜잭션이 시작된 후에 생성되므로 RR 수준에는 표시되지 않습니다.

세 번째 단계에서는 RC 수준의 경우 DB_TRX_ID가 활성 연결 목록에 없으면 DB_TRX_ID가 트랜잭션 ID보다 큰지 여부에 관계없이 RC가 표시됩니다.

RR 수준의 경우 low_limit_id가 현재 트랜잭션 id + 1이기 때문에 현재 트랜잭션이 생성되기 전에 low_limit_id보다 작은 트랜잭션이 나타난다고 볼 수 있으므로 DB_TRX_ID가 활성 연결 리스트에 있는지 간단히 판단하면 된다. .

직렬화 가능: 읽기와 쓰기가 모두 잠겨 있습니다

위 내용은 mysql의 격리 수준은 어떻게 구현됩니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿