>  기사  >  데이터 베이스  >  MySQL 트랜잭션과 MVCC가 달성하는 격리 수준에 대해 이야기해 보겠습니다.

MySQL 트랜잭션과 MVCC가 달성하는 격리 수준에 대해 이야기해 보겠습니다.

WBOY
WBOY앞으로
2022-01-26 17:11:102767검색

이 기사는 MySQL 트랜잭션의 격리 수준과 MVCC 구현 방법에 대한 몇 가지 질문을 제공합니다.

MySQL 트랜잭션과 MVCC가 달성하는 격리 수준에 대해 이야기해 보겠습니다.

데이터베이스 트랜잭션 소개

트랜잭션의 네 가지 주요 특성(ACID)

  1. 원자성(원자성): 모두 성공하거나 모두 실패하는 트랜잭션 작업의 가장 작은 단위입니다.

  2. 일관성: 트랜잭션이 시작되고 끝난 후에도 데이터베이스의 무결성은 파괴되지 않습니다.

  3. 격리: 서로 다른 트랜잭션은 서로 영향을 미치지 않습니다. RU(커밋되지 않은 읽기), RC(커밋된 읽기), RR(반복 읽기), SERIALIZABLE(직렬 변경)의 네 가지 격리 수준이 있습니다.

  4. 내구성: 거래가 제출된 후 데이터 수정 사항은 영구적이며 시스템이 실패하더라도 손실되지 않습니다.

트랜잭션 격리 수준

Read UnCommitted/RU

더티 읽기라고도 알려진 트랜잭션 하나는 다른 트랜잭션의 커밋되지 않은 데이터를 읽을 수 있습니다. 커밋되지 않은 트랜잭션은 롤백되기 때문에 이 격리 수준은 가장 안전하지 않습니다.

Read Committed/RC

Non-repeatable read라고도 하는 트랜잭션은 다른 트랜잭션에 의해 제출된 수정된 데이터를 읽으므로 현재 트랜잭션에서 서로 다른 시간에 동일한 항목을 읽게 됩니다. 데이터 수집 결과 일관성이 없습니다.

예를 들어 다음 예에서는 SessionA가 트랜잭션 중에 서로 다른 데이터를 두 번 쿼리하는 것을 볼 수 있습니다. 그 이유는 현재 격리 수준이 RC이고 SessionA의 트랜잭션은 SessionB가 제출한 최신 데이터를 읽을 수 있기 때문입니다.

발생 시간 SessionA SessionB
1 begin;
2 id=1인 사용자에서 *를 선택합니다.( Zhang San)
3
update user set name='lee思' 여기서 id=1; (기본 암시적 트랜잭션 커밋)
4 select * from user where id = 1;(이思)
5
update user set name='王two' 여기서 id=1;(기본 암시적 커밋 트랜잭션)
6 select * from user 여기서 id=1;(王이)

반복 읽기/RR)

또한팬텀 읽기라고도 알려져 있으며, 하나의 트랜잭션 읽기는 다른 트랜잭션 커밋을 읽을 수 있습니다. 그러나 RR 격리 수준에서는 이 데이터는 한 번만 읽을 수 있습니다. 현재 트랜잭션에서는 여러 번 읽어도 해당 데이터는 여전히 처음 읽은 값입니다. 읽기 후에는 다른 트랜잭션에서 데이터를 수정하고 커밋하여 변경 사항을 생성합니다. 따라서 읽어낸 데이터가 반드시 최신 데이터는 아니기 때문에 팬텀 읽기도 됩니다.

예: SessionA에서 처음으로 데이터를 읽을 때 제출된 데이터를 수정하는 후속 트랜잭션은 SessionA에서 읽은 데이터 값에 영향을 미치지 않습니다. 이는 반복 가능입니다.

발생 시간 SessionA SessionB
1 begin;
2 id=1인 사용자에서 *를 선택합니다.( Zhang San)
3
update user set name='lee思' 여기서 id=1; (기본 암시적 트랜잭션 제출)
4 select * from user where id = 1;(Zhang San)
5
update user set name='王two' 여기서 id=1;(기본 암시적 트랜잭션 커밋)
6 select * from user where id=1;(张三)

Serialized

모든 데이터베이스 읽기 또는 쓰기 작업은 순차적으로 실행되며, 현재 격리 수준에서는 단 하나만 지원됩니다. 요청이 동시에 실행되고, 모든 작업에는 대기열 실행이 필요합니다. 따라서 이 격리 수준 아래의 모든 데이터는 가장 안정적이지만 성능도 최악입니다. 데이터베이스의 잠금 구현은 이 격리 수준의 더 작은 세부 버전입니다.

발생 시간 SessionA SessionB
1 begin;
2
시작;
3
update user set name='lee思' where id=1;
4 select * from user where id=1;(잠깐, 잠깐)
5
commit;
6 select * from user where id=1;(lee思)

트랜잭션 및 MVCC 원칙

동일한 데이터를 동시에 운영하는 여러 트랜잭션으로 인해 발생하는 문제

예:

발생 시간 SessionA SessionB
1 begin ;
2
begin;
3
잔액 확인 = 1000위안
4 잔액 확인 = 1000위안
5
입금금액 100위안, 수정잔액 1100위안
6 현금 100위안 인출, 이때 수정잔액 900위안
8
거래 제출(잔액 = 1100)
9 거래 제출(잔액 = 900)
45689

위 두 가지 상황은 하나의 데이터에 대해 여러 트랜잭션이 동시에 작동할 때 발생할 수 있는 문제입니다. 특정 트랜잭션의 작업을 덮어쓰게 되어 데이터가 손실될 수 있습니다.

LBCC는 데이터 손실을 해결합니다

LBCC, 잠금 기반 동시성 제어.

잠금 메커니즘을 사용하면 현재 트랜잭션이 데이터를 수정해야 할 때 현재 트랜잭션이 잠깁니다. 동시에 하나의 트랜잭션만 현재 데이터를 수정할 수 있으며 다른 트랜잭션은 잠금이 해제될 때까지 기다려야 합니다. 작동하기 전에.

MVCC는 데이터 손실을 해결합니다

MVCC, 다중 버전 동시성 제어, 다중 버전 동시성 제어.

버전을 사용하여 동시성 데이터 문제를 제어합니다. 트랜잭션 B가 계정 수정을 시작하고 트랜잭션이 제출되지 않은 경우 트랜잭션 A가 계정 잔액을 읽어야 하는 경우 트랜잭션 B의 수정 작업 전 계정 잔액을 읽습니다. 데이터를 복사하지만, 트랜잭션 A가 계정 잔액 데이터를 수정해야 하는 경우 트랜잭션 B가 트랜잭션을 커밋할 때까지 기다려야 합니다.

MVCC는 데이터를 잠그지 않고 데이터베이스를 읽을 수 있으며 일반 SELECT 요청은 잠기지 않으므로 데이터베이스의 동시 처리 기능이 향상됩니다. MVCC의 도움으로 데이터베이스는 READ COMMITTED 및 REPEATABLE READ와 같은 격리 수준을 구현할 수 있습니다. 사용자는 현재 데이터의 이전 또는 이전 기록 버전을 볼 수 있으며 ACID의 I 기능(격리)을 보장할 수 있습니다.

InnoDB의 MVCC 구현 로직

InnoDB 스토리지 엔진이 저장하는 MVCC 데이터

InnoDB의 MVCC는 레코드의 각 행 뒤에 두 개의 숨겨진 열을 저장하여 구현됩니다. 행을 저장하는 트랜잭션 ID(DB_TRX_ID)와 행을 저장하는 롤백 포인터(DB_ROLL_PT). 새로운 거래가 시작될 때마다 새로운 거래 ID가 자동으로 증가됩니다. 트랜잭션 시작 시 현재 트랜잭션의 영향을 받는 트랜잭션 ID 행에 트랜잭션 ID가 배치되며, 쿼리 시 현재 트랜잭션 ID와 각 행에 기록된 트랜잭션 ID를 비교해야 합니다.

REPEATABLE READ 격리 수준에서 MVCC가 어떻게 작동하는지 살펴보겠습니다.

SELECT

InnoDB는 다음 두 가지 조건에 따라 각 행 레코드를 확인합니다.

  1. InnoDB는 버전이 현재 트랜잭션 버전보다 이전인 데이터 행만 찾습니다(즉, 행의 트랜잭션 번호는 현재 트랜잭션 버전 번호보다 작거나 같음), 이는 트랜잭션이 읽은 행이 트랜잭션이 시작되기 전에 이미 존재했거나 트랜잭션 자체에 의해 삽입 또는 수정되었음을 보장합니다.

  2. 삭제된 행은 트랜잭션 ID로 판단해야 하며, 트랜잭션을 읽기 전 상태의 버전만 쿼리 결과로 반환할 수 있습니다.

INSERT

InnoDB는 현재 트랜잭션 번호를 새로 삽입된 각 행의 행 버전 번호로 저장합니다.

DELETE

InnoDB는 현재 트랜잭션 번호를 삭제된 각 행의 행 삭제 식별자로 저장합니다.

UPDATE

InnoDB는 새 레코드 행을 삽입하고 현재 트랜잭션 번호를 행 버전 번호로 저장하며 현재 트랜잭션 번호를 행 삭제 식별자로 원래 행에 저장합니다.

대부분의 읽기 작업을 잠그지 않고 수행할 수 있도록 이 두 개의 추가 트랜잭션 번호를 저장하세요. 이 디자인은 데이터 읽기 작업을 매우 간단하게 만들고 성능도 매우 좋으며 표준을 충족하는 행만 읽도록 보장합니다. 단점은 각 레코드 행에 추가 저장 공간, 더 많은 행 확인 및 일부 추가 유지 관리 작업이 필요하다는 것입니다.

MVCC는 REPEATABLE READ와 READ COMMITIED라는 두 가지 격리 수준에서만 작동합니다. 다른 두 격리 수준은 READ UNCOMMITIED가 항상 현재 트랜잭션 버전을 준수하는 데이터 행이 아닌 최신 데이터 행을 읽기 때문에 MVCC와 호환되지 않습니다. SERIALIZABLE은 읽은 모든 행을 잠급니다.

mysql에서 MVCC 구현은 실행 취소 로그 및 읽기 보기에 의존합니다.

실행 취소 로그

실행 취소 로그는 두 가지 유형으로 나뉩니다: 실행 취소 로그 삽입실행 취소 로그 업데이트

  • 실행 취소 로그 삽입:

실행 취소 로그 삽입 는 작업 로그, 삽입 작업 기록은 현재 트랜잭션 자체에만 해당되고 다른 트랜잭션에는 표시되지 않기 때문에 제거 작업 없이 트랜잭션이 제출된 후 삽입 취소 로그를 바로 삭제할 수 있습니다.

제거의 주요 작업은 데이터베이스에서 del로 표시된 데이터를 삭제하는 것입니다. 또한 실행 취소 페이지도 일괄적으로 재활용합니다.

데이터베이스 삽입 시 초기 데이터 상태:

  • update 실행 취소 로그:

    update 또는 삭제 작업 중에 생성된 실행 취소 로그입니다. 이는 기존 레코드에 영향을 미치기 때문에 MVCC 메커니즘을 제공하기 위해 트랜잭션이 제출될 때 업데이트 실행 취소 로그를 삭제할 수 없습니다. 대신 트랜잭션이 제출될 때 기록 목록에 배치되어 제거 스레드가 수행될 때까지 기다립니다. 마지막 삭제 작업.

    데이터가 처음 수정된 경우:

다른 트랜잭션이 현재 데이터를 두 번째로 수정한 경우:

실행 중 해당 언두 로그를 작성할 때 트랜잭션이 충돌하지 않도록 하기 위해 동시 작업, InnoDB 롤백 세그먼트를 사용하여 실행 취소 로그의 동시 쓰기 및 지속성을 유지합니다. 롤백 세그먼트는 실제로 실행 취소 파일을 구성하는 방법입니다.

읽기보기

RU(READ UNCOMMITTED) 격리 수준의 경우 모든 트랜잭션이 데이터베이스의 최신 값을 직접 읽을 수 있으며 SERIALIZABLE 격리 수준의 경우 모든 요청이 잠기고 동기적으로 실행됩니다. 따라서 이 두 가지 경우에는 읽기 보기 버전 관리를 사용할 필요가 없습니다.

RC(READ COMMITTED)RR(REPEATABLE READ)의 경우 위의 버전 관리를 통해 격리 수준 구현이 완료됩니다. 두 가지 격리 범주 아래의 핵심 처리 논리는 모든 버전 중에서 현재 트랜잭션에 표시되는 버전을 결정하는 것입니다. 이 문제를 해결하기 위해 InnoDB는 ReadView 디자인을 추가했습니다. ReadView는 주로 현재 시스템에 있는 다른 활성 읽기 및 쓰기 트랜잭션을 포함하고 해당 트랜잭션 ID를 m_ids라는 이름으로 지정했습니다. .

쿼리 중 버전 체인 데이터가 표시되는지 여부에 대한 판단 논리:

  • 접근한 버전의 trx_id 속성 값이 m_ids 목록에서 가장 작은 트랜잭션 ID보다 작으면 해당 버전을 생성한 트랜잭션을 의미합니다. ReadView가 생성되기 전에 제출되었으므로 현재 트랜잭션에서 이 버전에 액세스할 수 있습니다.

  • 접근한 버전의 trx_id 속성 값이 m_ids 목록에서 가장 큰 트랜잭션 ID보다 큰 경우, 이 버전을 생성한 트랜잭션이 ReadView가 생성된 후에 생성되었으므로 이 버전에 접속할 수 없음을 나타냅니다. 현재 거래로 인해.

  • 접근한 버전의 trx_id 속성 값이 m_ids 목록의 가장 큰 트랜잭션 ID와 가장 작은 트랜잭션 ID 사이에 있는 경우 trx_id 속성 값이 m_ids 목록에 있는지 확인해야 합니다. ReadView를 생성할 때 생성되었음을 의미합니다. 이 버전의 트랜잭션이 여전히 활성 상태이고, 그렇지 않은 경우 이 버전에 액세스할 수 없다는 의미입니다. 이는 ReadView가 생성될 때 이 버전을 생성한 트랜잭션이 커밋되었으며 이 버전을 사용할 수 있음을 의미합니다. 액세스했습니다.

예:

READ COMMITTED 격리 수준에서 ReadView

데이터를 읽기 전에 항상 ReadView(m_ids 목록)를 생성하세요

발생 시간 SessionA SessionB
1 begin;
2
begin;
3
잔액 확인 = 1000위안
잔액 확인 = 1000위안

입금액은 100위안, 수정 잔액은 1100위안
100위안 인출 현금 및 수정된 잔액 현재 900위안입니다

거래 제출(잔고 = 1100)
거래 취소(잔고가 1000위안으로 복원됨)
Time 트랜잭션 작업 777 거래 888 거래 999
T1 begin;

T2
시작; 시작;
T3 업데이트 사용자 세트 이름 = 'CR7' WHERE id = 1;

T4
...
T 5 UPD ATE 사용자 SET 이름 = '메시 ' WHERE id = 1;
SELECT * FROM user where id = 1;
T6 commit;

T7
UPDATE 사용자 설정 이름 = 'Neymar' WHERE id = 1;
T8

SELECT * FROM user where id = 1;
T9
UPDATE 사용자 SET 이름 = '디발라 ' WHERE ID = 1;
T10
commit;
T11

SELECT * ID = 1인 FROM 사용자;

위 상황에서의 ReadView 분석은 다음과 같습니다

T5 시점의 SELECT 문:

현재 시점의 버전 체인:

이 때 SELECT 문이 실행되며, 의 버전 체인은 다음과 같습니다. 현재 데이터는 위와 같습니다. 현재 트랜잭션 777과 트랜잭션 888이 제출되지 않았기 때문에 현재 활성 트랜잭션의 ReadView 목록은 m_ids: [777, 888]이므로 쿼리 문은 다음을 기반으로 합니다. m_ids보다 작은 현재 버전 체인의 가장 큰 버전 데이터입니다. 즉, 쿼리는 Mbappe입니다.

T8시점의 SELECT 문:

현재 버전 체인 상황:

이때 SELECT 문이 실행되는데, 현재 데이터의 버전 체인은 위와 같습니다. 777은 제출되었고, 888번 거래는 제출되지 않았으므로 현재 활성 거래의 ReadView 목록은 m_ids: [888]이므로 쿼리 문은 현재 버전에서 가장 큰 버전 데이터를 기반으로 합니다. m_ids 보다 작은 체인, 즉 메시가 쿼리됩니다.

T11 시점의 SELECT 문:

현재 시점의 버전 체인 정보:

이 때, SELECT 문이 실행되며 현재 트랜잭션이 있기 때문에 현재 데이터의 버전 체인은 위와 같습니다. 777 및 트랜잭션 888이 제출되었으므로 현재 활성 트랜잭션에 대한 ReadView 목록이 비어 있으므로 쿼리 문은 현재 데이터베이스의 최신 데이터, 즉 Dybala에 쿼리됩니다.

요약: READ COMMITTED 격리 수준을 사용하는 트랜잭션은 각 쿼리 시작 시 독립적인 ReadView를 생성합니다.

REPEATABLE READ 격리 수준의 ReadView

트랜잭션 시작 후 처음으로 데이터를 읽을 때 ReadView(m_ids 목록)를 생성합니다.

ECT * ID = 1인 사용자로부터;
Time 트랜잭션 777 거래액션 888 거래액 999
T1 begin;

T2
시작; 시작;
T3 업데이트 사용자 세트 이름 = 'CR7' WHERE ID = 1;

T4
...
T5 UPDATE 사용자 SET 이름 = '메시' WHERE id = 1;
SELECT * FROM user where id = 1;
T6 commit;

T7
UPDATE 사용자 SET 이름 = ' Neymar' WHERE id = 1;
T8

SELECT * FROM user where id = 1;
T9
UP DATE 사용자 설정 이름 = '디발라 ' ID = 1;
T10
commit;
T11

T5의 경우 시점 SELECT 문:

현재 버전 체인:

A ReadView는 현재 select 문이 실행될 때 생성됩니다. 이때

m_ids의 내용은 [777,888]이므로 ReadView의 표시 버전에 따라 쿼리되는 데이터는 Mbappe입니다.

T8 시점의 SELECT 문:

현재 버전 체인:

현재 트랜잭션 999입니다. ReadView는 T5 시점에 생성되었으므로 ReadView는 현재 트랜잭션에서 한 번만 생성되므로 T5의

m_ids([777,999])가 여전히 사용되므로 이 시점의 쿼리 데이터는 여전히 Mbappe입니다.

T11 시점의 SELECT 문:

현재 버전 체인:

지금의 상황은 T8과 완전히 동일합니다. ReadView는 T5 시점에 생성되었으므로 ReadView는 현재 트랜잭션에서 한 번만 생성되므로 T5의

m_ids([777,999])가 여전히 사용되므로 이 시점의 쿼리 데이터는 여전히 Mbappe입니다.

MVCC 요약:

소위 MVCC(다중 버전 동시성 제어, 다중 버전 동시성 제어)는

READ COMMITTDREPEATABLE READ의 두 가지 격리 수준을 사용하여 일반 트랜잭션을 실행하는 것을 의미합니다. SEELCT 작업은 기록된 버전 체인에 액세스하는 프로세스로, 이를 통해 서로 다른 트랜잭션의 작업을 동시에 실행할 수 있어 시스템 성능이 향상됩니다. 读-写 、 写-读

추천 학습:

mysql 비디오 튜토리얼

위 내용은 MySQL 트랜잭션과 MVCC가 달성하는 격리 수준에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 csdn.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제