답변:
커밋 된 읽기는 현재 커밋 된 모든 데이터를 읽도록 보장하는 격리 수준입니다 . 그것은 독자가 중간의 커밋되지 않은 '더러운'읽기를 보지 못하게합니다. 트랜잭션이 읽기를 다시 발행하고 동일한 데이터 를 찾을 경우 데이터를 읽은 후 자유롭게 변경할 수 있다는 약속은 없습니다 .
반복 가능한 읽기는 더 높은 격리 수준으로, 읽기 커밋 된 수준의 보장 외에도 모든 데이터 읽기 가 변경 될 수 없음을 보장합니다 . 트랜잭션이 동일한 데이터를 다시 읽는 경우 이전에 읽은 데이터가 변경되지 않은 채로 있음을 알 수 있습니다. 읽고 읽을 수 있습니다.
직렬화 가능한 다음 격리 수준은 더욱 강력한 보증을 제공합니다. 반복 가능한 읽기 보장 외에도 모든 후속 읽기에서 새로운 데이터 를 볼 수 없도록 보장합니다 .
하나의 행이있는 C 열이있는 테이블 T가 있고 값이 '1'이라고 가정하십시오. 그리고 다음과 같은 간단한 작업이 있다고 생각하십시오.
BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;
이는 테이블 T에서 두 번의 읽기를 발생시키는 간단한 작업입니다.
위의 논리를 따르면 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.
오래된 대답은 이미 받아 들였지만 SQL Server에서 잠금 동작을 어떻게 변경하는지에 관해서는이 두 가지 격리 수준을 생각하고 싶습니다. 이것은 내가했던 것처럼 교착 상태를 디버깅하는 사람들에게 도움이 될 수 있습니다.
읽기 커밋 됨 (기본값)
공유 잠금은 SELECT에서 가져온 다음 SELECT 문이 완료되면 해제 됩니다 . 커밋되지 않은 데이터에 대한 더티 판독이 없음을 시스템이 보장 할 수있는 방법입니다. 다른 트랜잭션은 여전히 SELECT가 완료된 후와 트랜잭션이 완료되기 전에 기본 행을 변경할 수 있습니다.
반복 가능한 읽기
공유 잠금은 SELECT에서 가져온 다음 트랜잭션이 완료된 후에 만 해제 됩니다 . 이렇게하면 시스템이 트랜잭션 중에 읽은 값이 변경되지 않도록 보장 할 수 있습니다 (트랜잭션이 완료 될 때까지 값이 잠겨 있기 때문).
간단한 다이어그램으로이 의심을 설명하려고합니다.
커밋 된 읽기 : 여기서이 격리 수준에서 트랜잭션 T1은 트랜잭션 T2가 커밋 한 X의 업데이트 된 값을 읽습니다.
반복 가능한 읽기 : 이 격리 수준에서 트랜잭션 T1은 트랜잭션 T2가 커밋 한 변경 사항을 고려하지 않습니다.
는 점에 유의하시기 바랍니다 반복 하지만 전체 테이블에, 튜플에 대한 반복 읽기의 안부를. ANSC 격리 수준에서 팬텀 읽기 이상이 발생할 수 있습니다. 즉, where 절이 동일한 테이블을 두 번 읽으면 서로 다른 결과 집합을 반환 할 수 있습니다. 말 그대로 반복 할 수 없습니다 .
처음 수락 된 솔루션에 대한 나의 관찰.
RR에서 (기본 mysql)-tx가 열려 있고 SELECT가 실행 된 경우 다른 tx는 이전 tx가 커밋 될 때까지 이전 READ 결과 집합에 속하는 행을 삭제할 수 없습니다 (사실 새 tx의 delete 문은 중단됨) 그러나 다음 tx는 문제없이 테이블에서 모든 행 을 삭제할 수 있습니다 . Btw, 이전 tx의 다음 READ는 커밋 될 때까지 이전 데이터를 계속 볼 수 있습니다.