집 >데이터 베이스 >MySQL 튜토리얼 >MySQL 잠금, 트랜잭션 및 MVCC에 대한 간략한 이해
더 많은 관련 무료 학습 권장 사항: mysql 튜토리얼(동영상)
다음 내용은 "고성능 MySQL"(3판)에서 발췌한 내용입니다
"MySQL은 기본적으로 자동 커밋(AUTOCOMMIT) 모드를 채택합니다. 즉, 트랜잭션이 명시적으로 시작되지 않는 경우 , 각 쿼리는 커밋 작업을 수행하는 트랜잭션으로 처리됩니다. 현재 연결에서는 AUTOCOMMIT 변수
"
트랜잭션에는 ACID의 네 가지 특성이 있습니다. 그러면 MySQL은 이 네 가지 트랜잭션 특성을 어떻게 구현합니까?
원자적 모두 성공하거나 모두 실패합니다. MySQL은 undo_log를 기록하여 원자성을 달성합니다. undo_log는 rollback log로, 실제 SQL이 실행되기 전에 디스크에 기록된 후 데이터베이스 데이터가 작동됩니다. 예외나 롤백이 발생하면 undo_log를 기반으로 역방향 작업을 수행하여 트랜잭션이 실행되기 전의 데이터를 복원할 수 있습니다.
끈기 트랜잭션이 정상적으로 커밋되면 데이터베이스에 미치는 영향은 영구적이어야 합니다. 이때 시스템이 충돌하더라도 수정된 데이터는 손실되지 않습니다. InnoDB는 MySQL의 스토리지 엔진으로 데이터가 디스크에 저장된다. 그러나 데이터를 읽고 쓸 때마다 디스크 IO가 필요하면 효율성이 매우 떨어진다. 이를 위해 InnoDB는 데이터베이스에 접근하기 위한 버퍼로 캐시(Buffer Pool)를 제공하는데, 데이터베이스에서 데이터를 읽을 때 버퍼 풀에 없으면 먼저 읽어온다. 데이터베이스에 데이터를 쓸 때 먼저 버퍼 풀에 기록되고 버퍼 풀의 수정된 데이터가 정기적으로 디스크에 새로 고쳐집니다.
이러한 설계는 또한 상응하는 문제를 가져옵니다. 데이터가 제출되고 데이터가 여전히 버퍼 풀에 있는 경우(디스크가 아직 플러시되지 않은 경우) MySQL이 다운되거나 전원이 꺼지면 어떻게 해야 합니까? 데이터가 손실되나요?
대답은 '아니오'입니다. MySQL은 redo_log 메커니즘을 통해 내구성을 보장합니다. redo_log는 redo 로그입니다. 간단히 말해서, 데이터가 수정되면 버퍼 풀의 데이터를 수정하는 것 외에도 트랜잭션이 제출될 때 작업이 redo_log에 기록되고 fsync 인터페이스가 호출됩니다. redo_log. MySQL이 다운되면 redo_log의 데이터를 읽고 다시 시작할 때 데이터베이스를 복구할 수 있습니다.
Isolation
Isolation은 ACID에서 가장 복잡한 것으로, 총 4가지의 격리 레벨이 있습니다
간단히 말해서 격리 수준은 다음을 규정합니다. 트랜잭션의 데이터 수정, 어떤 트랜잭션이 표시되고 표시되지 않는지. 격리는 여러 동시 읽기 및 쓰기 요청의 액세스 순서를 관리하는 것입니다.
MySQL의 구체적인 격리 구현에 대해서는 나중에 논의할 것입니다.
일관성
동시 환경에서 롤백, 복구, 격리를 통해 일관성을 달성하세요.
앞의 질문을 통해 단일 DDL 실행도 자동으로 트랜잭션으로 제출된다는 것을 알고 있으므로 동시에 여러 SQL이든 다중 수동으로 여러 SQL 문을 포함하는 조직의 트랜잭션 동시성은 트랜잭션 동시성 문제를 발생시킵니다.
구체적으로:
앞서 언급한 바가 있습니다 위의 트랜잭션 격리 수준 MySQL의 모든 격리 수준은 더티 쓰기가 발생하지 않도록 보장하므로 남은 문제는 더티 읽기, 반복 불가능한 읽기 및 팬텀 읽기뿐입니다.
각 격리 수준이 위의 문제를 어떻게 해결하거나 해결하지 못하는지 자세히 살펴보겠습니다.
Uncommitted 읽기, 이 수준은 읽기 프로세스 중에 잠금을 추가하지 않습니다. , 요청을 쓸 때만 잠기므로 쓰기 작업은 읽기 프로세스 중에 데이터를 수정하므로 더티 읽기가 발생합니다. 반복 불가능한 읽기와 팬텀 읽기는 자연스럽게 발생합니다.
커밋된 읽기는 커밋되지 않은 읽기와 마찬가지로 읽기용으로 잠기지 않고 쓰기용으로 잠겨 있습니다. 차이점은 더티 읽기(dirty read) 문제를 방지하기 위해 MVCC 메커니즘이 사용된다는 것입니다. 반복 불가능한 읽기 및 팬텀 읽기 문제도 있습니다. MVCC에 대해서는 나중에 자세히 설명하겠습니다.
MySQL 기본 격리 수준에서 MySQL은 문제를 해결하기 위해 두 가지 방법을 사용합니다.
또한, 팬텀리딩 문제를 어느 정도 해결하기 위해 Next-Key 잠금도 사용됩니다. 이에 대해서는 나중에 이야기하겠습니다.
이 격리 수준에서는 트랜잭션이 순차적으로 실행됩니다. 자동 커밋이 비활성화된 경우 InnoDB는 모든 일반 SELECT 문을 암시적으로 SELECT ... LOCK IN SHARE MODE로 변환합니다. 즉, 읽기 공유 잠금이 읽기 작업에 암시적으로 추가되어 더티 읽기, 반복 불가능 읽기 및 팬텀 읽기 문제를 방지합니다. 다중 버전 동시성 제어(MCC 또는 MVCC)는 데이터베이스에 대한 동시 액세스를 제공하고 트랜잭션 메모리를 구현하기 위해 프로그래밍 언어로 데이터베이스 관리 시스템에서 일반적으로 사용되는 동시성 제어 방법입니다.
우리가 일반적으로 사용하는 MySQL을 예로 들면, MySQL의 InnoDB 엔진은 MVCC를 구현합니다. MVCC가 해결할 수 있는 문제
위 정의에서 MVCC는 주로 트랜잭션 동시성 중 데이터 일관성 문제를 해결한다는 것을 알 수 있습니다
아래 그림은 "고성능 MySQL"(3판)에서 가져온 것입니다.
이 책은 잘 쓰여지고 잘 번역되었습니다. 하지만 개인적으로 MVCC 구현 방법에 대한 설명에는 몇 가지 문제가 있다고 생각합니다.
어디가 문제인지 살펴보겠습니다
먼저 MySQL 공식 문서를 살펴보겠습니다. 5.1, 5.6, 5.7 세 가지 버전[1]의 문서를 비교했습니다. MVCC의 이 부분을 설명하는 내용은 거의 동일합니다.
문서에 따르면 각 데이터 조각에 3개의 숨겨진 열이 추가된 것이 분명합니다.
여기에 롤백 세그먼트를 포함한 MySQL 내부 구조 다이어그램을 추가합니다
버전 체인
앞에서 undo_log의 개념에 대해 이야기했습니다. 버전 체인의 헤드 노드는 현재 레코드의 최신 값입니다.
읽기보기
열과 버전 체인을 숨김으로써 MySQL은 데이터를 지정된 버전으로 복원할 수 있지만 복원할 버전은 ReadView에 따라 결정되어야 합니다. 소위 ReadView는 트랜잭션(트랜잭션 A로 기록됨)이 특정 순간에 전체 트랜잭션 시스템(trx_sys)의 스냅샷을 찍는 것을 의미하며, 나중에 읽기 작업이 수행될 때 읽기 데이터의 트랜잭션 ID와 비교됩니다. trx_sys 스냅샷을 통해 데이터가 ReadView에 표시되는지, 즉 트랜잭션 A에 표시되는지 여부를 결정합니다.
지금까지 우리는 MVCC가 숨겨진 필드, undo_log 체인 및 ReadView를 기반으로 구현된다는 것을 발견했습니다.
이전에 우리는 더티 읽기 문제를 해결하기 위해 읽기 커밋 격리 수준에서 MVCC를 사용하는 방법에 대해 이야기했습니다. 여기서는 두 가지 기사를 참조합니다.
InnoDB 버전이 현재 트랜잭션 버전보다 이전인 데이터 행만 찾습니다(즉, 행의 버전 번호가 트랜잭션의 시스템 버전 번호보다 작거나 같음). 트랜잭션이 시작되기 전에 이미 존재하며 트랜잭션 자체에 의해 삽입되거나 수정됩니다. 그러면 더티 읽기가 발생하지 않습니다.
commitRead 격리 수준에서 반복 불가능한 읽기는 읽기 보기의 생성 메커니즘으로 인해 발생합니다. Read 커밋 수준에서는 현재 문이 실행되기 전에 커밋된 데이터가 표시됩니다. 각 명령문 실행 중에 읽기 보기가 닫히고 현재 읽기 보기가 다시 생성됩니다. 이러한 방식으로 현재 글로벌 트랜잭션 목록을 기반으로 읽기 뷰의 트랜잭션 간격을 생성할 수 있습니다. 간단히 말해서, 읽기 커밋 격리 수준에서 MVCC는 각 선택에 대해 스냅샷 버전을 생성하므로 각 선택은 서로 다른 버전의 데이터를 읽으므로 반복 불가능한 읽기가 발생합니다.
반복 읽기 격리 수준은 반복 불가능 읽기 문제를 해결할 수 있습니다. 근본적인 이유는 읽기 뷰의 생성 메커니즘이 읽기 커밋의 생성 메커니즘과 다르기 때문입니다.
읽기 커밋과 달리 반복 읽기 격리 수준에서 트랜잭션이 생성되면 현재 전역 읽기 뷰가 생성되어 트랜잭션이 끝날 때까지 유지됩니다. 이를 통해 반복 가능한 읽기가 가능해집니다.
MVCC 메커니즘을 통해 데이터는 반복 가능하지만 우리가 읽는 데이터는 기록 데이터입니다. , 시기적절한 데이터가 아니고 데이터베이스의 현재 데이터가 아닙니다! 이러한 기록 데이터 읽는 방법을 스냅샷 읽기(스냅샷 읽기)라고 하고, 현재 버전의 데이터베이스 데이터를 읽는 방법을 현재 읽기(현재 읽기) Reference[3]이라고 합니다.
반복 읽기는 다음 키 잠금 메커니즘을 통해 가상 읽기를 방지합니다.
InnoDB 스토리지 엔진에는 다음과 같은 3개의 행 잠금 알고리즘이 있습니다.
다음 키 잠금은 행 잠금 유형으로, 레코드 잠금 + 갭 잠금과 동일하며 그 특징은 레코드 자체를 유지할 뿐만 아니라(기능) 기록 잠금 기능), 범위 잠금 기능(갭 잠금 기능)도 있습니다.
InnoDB가 인덱스 레코드를 스캔할 때 먼저 인덱스 레코드에 행 잠금(Record Lock)을 추가한 다음 인덱스 레코드 양쪽의 간격에 간격 잠금(Gap Lock)을 추가합니다. 갭 잠금을 추가한 후에는 다른 트랜잭션이 이 갭의 레코드를 수정하거나 삽입할 수 없습니다.
쿼리된 인덱스에 고유 속성이 포함된 경우 Next-Key Lock이 최적화되어 범위가 아닌 인덱스 자체만 잠그는 Record Lock으로 다운그레이드됩니다.
위 내용은 MySQL 잠금, 트랜잭션 및 MVCC에 대한 간략한 이해의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!