[sql] “읽기 커밋 된”및 “반복 가능한 읽기”의 차이점

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



답변

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

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

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

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

보충 자료 :


답변

반복 가능한 읽기

데이터베이스의 상태는 트랜잭션 시작부터 유지됩니다. 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

말이된다?


답변

이 스레드에 대한 나의 독서와 이해에 따른 대답은 @ 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는 테이블에서 읽거나 쓸 수 없습니다. 테이블 레벨 블록
  • 스냅 샷 : 모든 프로세스에는 자체 사본이 있으며 작업 중입니다. 각각의 관점이 있습니다

답변

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

읽기 커밋 됨 (기본값)

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

반복 가능한 읽기

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


답변

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

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

커밋 된 읽기

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

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


답변

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

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


답변

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