"읽기 커밋 된"및 "반복 가능한 읽기"의 차이점


245

위의 격리 수준이 너무 비슷하다고 생각합니다. 누군가 주요한 차이점이 무엇인지 멋진 예제로 설명해 주시겠습니까?


3
질문을 확장하고 어떤 "격리 수준"(Java 등)을 나타내는 태그를 추가해야합니다. "격리 수준"은 다소 모호한 용어이며 특정 환경에 대한 대답을 분명히 요구하고 있습니다.
jesup

답변:


564

커밋 된 읽기는 현재 커밋 된 모든 데이터를 읽도록 보장하는 격리 수준입니다 . 그것은 독자가 중간의 커밋되지 않은 '더러운'읽기를 보지 못하게합니다. 트랜잭션이 읽기를 다시 발행하고 동일한 데이터 를 찾을 경우 데이터를 읽은 후 자유롭게 변경할 수 있다는 약속은 없습니다 .

반복 가능한 읽기는 더 높은 격리 수준으로, 읽기 커밋 된 수준의 보장 외에도 모든 데이터 읽기 가 변경 될 수 없음을 보장합니다 . 트랜잭션이 동일한 데이터를 다시 읽는 경우 이전에 읽은 데이터가 변경되지 않은 채로 있음을 알 수 있습니다. 읽고 읽을 수 있습니다.

직렬화 가능한 다음 격리 수준은 더욱 강력한 보증을 제공합니다. 반복 가능한 읽기 보장 외에도 모든 후속 읽기에서 새로운 데이터 를 볼 수 없도록 보장합니다 .

하나의 행이있는 C 열이있는 테이블 T가 있고 값이 '1'이라고 가정하십시오. 그리고 다음과 같은 간단한 작업이 있다고 생각하십시오.

BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;

이는 테이블 T에서 두 번의 읽기를 발생시키는 간단한 작업입니다.

  • READ COMMITTED에서 두 번째 SELECT는 모든 데이터를 반환 수 있습니다. 동시 트랜잭션은 레코드를 업데이트하고 삭제하고 새 레코드를 삽입 할 수 있습니다. 두 번째 선택은 항상 새로운 데이터를 보게 됩니다.
  • REPEATABLE READ 아래에서 두 번째 SELECT는 최소한 첫 번째 SELECT에서 반환 된 행을 변경하지 않고 표시 합니다. 1 분 안에 동시 트랜잭션으로 새 행을 추가 할 수 있지만 기존 행을 삭제하거나 변경할 수 없습니다.
  • SERIALIZABLE 아래에서 두 번째 선택은 첫 번째와 정확히 동일한 행 을 볼 있습니다. 동시 트랜잭션으로 행을 변경하거나 삭제하거나 새 행을 삽입 할 수 없습니다.

위의 논리를 따르면 SERIALIZABLE 트랜잭션은 사용자가 삶을 쉽게 만들 수 있지만 행을 수정, 삭제 또는 삽입 할 수있는 사람이 없어야하므로 가능한 모든 동시 작업을 항상 완전히 차단 하고 있음을 신속하게 알 수 있습니다 . .Net System.Transactions범위 의 기본 트랜잭션 격리 수준 은 직렬화 가능하며 이는 일반적으로 발생하는 끔찍한 성능을 설명합니다.

마지막으로 SNAPSHOT 격리 수준도 있습니다. SNAPSHOT 격리 수준은 직렬화와 동일한 보장을 제공하지만 동시 트랜잭션이 데이터를 수정할 수있는 것은 아닙니다. 대신, 모든 독자가 자신의 세계 버전 (자신의 '스냅 샷')을 보게합니다. 따라서 동시 업데이트를 차단하지 않으므로 프로그래밍하기가 쉽고 확장 성이 뛰어납니다. 그러나 그 이점은 추가 서버 리소스 소비라는 가격과 함께 제공됩니다.

보충 자료 :


24
REPEATABLE READ에 대해 위의 실수가 있다고 생각합니다. 기존 행을 삭제하거나 변경할 수 없다고 말하지만 반복 가능한 읽기는 실제 데이터가 아닌 "스냅 샷"을 읽기 때문에 행을 삭제하거나 변경할 수 있다고 생각합니다. docs dev.mysql.com/doc/refman/5.0/en/… : "같은 트랜잭션 내에서 모든 일관된 읽기는 첫 번째 읽기에서 설정 한 스냅 샷을 읽습니다."
데릭 리츠

2
@Derek Litz Am : 당신이 말하고있는 바로 맞습니다 : 거래가 진행되는 동안 데이터 CAN / MAY는 제 3 자로부터 변경 될 수 있지만 변경 사항이 수행되지 않은 것처럼 읽음에는 여전히 '오래된'원래 데이터가 표시됩니다 장소 (스냅 샷).
Programster

5
@Cornstalks. 예, 삭제 (또는 삽입)에서 팬텀 읽기가 발생할 수 있습니다. 예, 팬텀 읽기는 반복 가능한 읽기 분리 (삽입 만)에서 발생할 수 있습니다. 아니오, 삭제 가능한 팬텀 읽기는 반복 가능한 읽기 격리에서 발생할 수 없습니다. 그것을 테스트하십시오. 내가 말하는 것은 당신이 인용 한 문서와 모순되지 않습니다.
AndyBrown

4
@Cornstalks NP. 나는 100 % 자신을 확신하지 못했고 누가 옳은지 확신하기 위해 깊이 잠수해야했기 때문에 전혀 언급하지 않았습니다! 그리고 나는 미래의 독자들이 오도되기를 원하지 않았습니다. 의견을 유지하십시오. 아마 제안대로 유지하는 것이 가장 좋습니다. 나는 그 세밀한 수준의 세부 사항에 관심이있는 사람이라면 누구나 모든 의견을 읽을만큼 충분히 확신 할 것입니다!!
AndyBrown

12
댓글을 삭제하지 주셔서 감사합니다. 토론은 더 많은 점들을 연결하는 데 도움이됩니다.
Josh

68

반복 가능한 읽기

데이터베이스의 상태는 트랜잭션 시작부터 유지됩니다. session1에서 값을 검색 한 경우 session2에서 해당 값을 업데이트하면 session1에서 다시 검색하면 동일한 결과가 반환됩니다. 읽기는 반복 가능합니다.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Aaron

커밋 된 읽기

트랜잭션 컨텍스트 내에서 항상 가장 최근에 커밋 된 값을 검색합니다. session1에서 값을 검색하고 session2에서 값을 업데이트 한 다음 session1에서 다시 검색하면 session2에서 수정 된 값을 얻게됩니다. 마지막 커밋 된 행을 읽습니다.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Bob

말이된다?


"set isolation level repeatable read"로 SQL Server 2008에서 Repeatable Read를 시도했습니다. 두 개의 SQL 쿼리 창을 만들었습니다. 그러나 작동하지 않았다. 왜?
Aditya Bokade

1
두 번째 세션 1이 왜 여전히 아론을 읽었 을까요? session2의 트랜잭션이 완료 및 커밋되지 않았습니까? 나는이 오래된 것을 알고 있지만 어쩌면 누군가가 약간의 빛을 비출 수 있습니다.
Sonny Childs

9
반복 가능한 읽기는 첫 번째 세션이 커밋 될 때까지 두 번째 세션을 차단한다고 생각합니다. 따라서 예가 잘못되었습니다.
Nighon

4
반복 가능한 읽기의 경우 세션 1이 행을 읽을 때 공유 잠금을 설정하여 독점 잠금 (세션 2에 대한)을 허용하지 않으므로 데이터를 업데이트 할 수 없습니다.
Taher

두 트랜잭션 사이의 공유 행을 업데이트 할 때 SQL Server와 MySQL이 다르게 동작한다고 생각합니다.
user2488286

23

이 스레드에 대한 나의 독서와 이해에 따른 대답은 @ remus-rusanu 대답은 다음과 같은 간단한 시나리오를 기반으로합니다.

프로세스 A와 B에는 두 가지가 있습니다. 프로세스 B가 테이블 X를 읽는 중 프로세스 A가 테이블 X에 쓰는 중 프로세스 B가 다시 읽는 중 테이블 X.

  • ReadUncommitted : 프로세스 B는 프로세스 A에서 커밋되지 않은 데이터를 읽을 수 있으며 B 쓰기에 따라 다른 행을 볼 수 있습니다. 전혀 잠금이 없습니다
  • ReadCommitted : 프로세스 B는 프로세스 A에서 커밋 된 데이터 만 읽을 수 있으며 COMMITTED 만 B 쓰기에 따라 다른 행을 볼 수 있습니다. 단순 잠금이라고 부를 수 있을까요?
  • RepeatableRead : 프로세스 B는 프로세스 A가 무엇을 하든지 동일한 데이터 (행)를 읽습니다. 그러나 프로세스 A는 다른 행을 변경할 수 있습니다. 행 레벨 블록
  • 직렬화 가능 : 프로세스 B는 이전과 동일한 행을 읽고 프로세스 A는 테이블에서 읽거나 쓸 수 없습니다. 테이블 레벨 블록
  • 스냅 샷 : 모든 프로세스에는 자체 사본이 있으며 작업 중입니다. 각각의 관점이 있습니다

15

오래된 대답은 이미 받아 들였지만 SQL Server에서 잠금 동작을 어떻게 변경하는지에 관해서는이 두 가지 격리 수준을 생각하고 싶습니다. 이것은 내가했던 것처럼 교착 상태를 디버깅하는 사람들에게 도움이 될 수 있습니다.

읽기 커밋 됨 (기본값)

공유 잠금은 SELECT에서 가져온 다음 SELECT 문이 완료되면 해제 됩니다 . 커밋되지 않은 데이터에 대한 더티 판독이 없음을 시스템이 보장 할 수있는 방법입니다. 다른 트랜잭션은 여전히 ​​SELECT가 완료된 후와 트랜잭션이 완료되기 전에 기본 행을 변경할 수 있습니다.

반복 가능한 읽기

공유 잠금은 SELECT에서 가져온 다음 트랜잭션이 완료된 후에 만 해제 됩니다 . 이렇게하면 시스템이 트랜잭션 중에 읽은 값이 변경되지 않도록 보장 할 수 있습니다 (트랜잭션이 완료 될 때까지 값이 잠겨 있기 때문).


13

간단한 다이어그램으로이 의심을 설명하려고합니다.

커밋 된 읽기 : 여기서이 격리 수준에서 트랜잭션 T1은 트랜잭션 T2가 커밋 한 X의 업데이트 된 값을 읽습니다.

커밋 된 읽기

반복 가능한 읽기 : 이 격리 수준에서 트랜잭션 T1은 트랜잭션 T2가 커밋 한 변경 사항을 고려하지 않습니다.

여기에 이미지 설명을 입력하십시오


1

이 사진도 유용 할 수 있다고 생각합니다. 격리 수준의 차이를 빠르게 기억하고 싶을 때 참고 자료로 도움이됩니다 ( youtube의 kudvenkat 덕분에 ).

여기에 이미지 설명을 입력하십시오


0

는 점에 유의하시기 바랍니다 반복 하지만 전체 테이블에, 튜플에 대한 반복 읽기의 안부를. ANSC 격리 수준에서 팬텀 읽기 이상이 발생할 수 있습니다. 즉, where 절이 동일한 테이블을 두 번 읽으면 서로 다른 결과 집합을 반환 할 수 있습니다. 말 그대로 반복 할 수 없습니다 .


-1

처음 수락 된 솔루션에 대한 나의 관찰.

RR에서 (기본 mysql)-tx가 열려 있고 SELECT가 실행 된 경우 다른 tx는 이전 tx가 커밋 될 때까지 이전 READ 결과 집합에 속하는 행을 삭제할 수 없습니다 (사실 새 tx의 delete 문은 중단됨) 그러나 다음 tx는 문제없이 테이블에서 모든 행 을 삭제할 수 있습니다 . Btw, 이전 tx의 다음 READ는 커밋 될 때까지 이전 데이터를 계속 볼 수 있습니다.


2
답변자가 알림을 받도록 주석 섹션에 추가 할 수 있습니다. 그렇게하면 그는 당신의 관찰에 응답하고 필요할 경우 수정을 할 수있을 것입니다.
RBT
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.