커밋되지 않은 읽기 격리 수준을 사용해야하는 이유는 무엇입니까?


225

평범한 영어로, 사용의 단점과 장점은 무엇입니까

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

.NET 응용 프로그램 및보고 서비스 응용 프로그램에 대한 쿼리에서?

답변:


210

이 격리 수준은 더티 읽기를 허용합니다. 하나의 트랜잭션은 다른 트랜잭션에 의해 커밋되지 않은 변경 사항을 볼 수 있습니다.

최고 수준의 격리를 유지하기 위해 DBMS는 일반적으로 데이터에 대한 잠금을 획득하므로 동시성 손실과 높은 잠금 오버 헤드가 발생할 수 있습니다. 이 격리 수준은이 속성을 완화시킵니다.

몇 가지 예와 추가 정보 는 Wikipedia 기사READ UNCOMMITTED 를 확인하십시오 .


Jeff Overwood의 블로그 기사 에서 Stack Overflow 초기에 교착 상태 문제를 해결 한 방법에 대해 Jeff Atwood의 블로그 기사 를 확인하는 것이 좋습니다. Jeff에 따르면 :

그러나 nolock위험합니까? 에 잘못된 데이터를 읽게 될 수 read uncommitted있습니까? 예, 이론 상으로는 ACID 과학을 떨어 뜨리기 시작한 데이터베이스 아키텍처 우주 비행사가 부족하다는 것을 발견 할 수 있습니다 nolock. 사실이다 : 이론은 무섭다. 그러나 여기 제가 생각하는 것은 : "이론에는 이론과 실제에 차이가 없습니다. 실제로는 있습니다."

나는 nolock 데이터베이스 교착 상태 문제에 대해 일반적인 "당신을 위해 좋은"뱀 기름 수정으로 사용 하는 것을 권장하지 않을 것입니다. 먼저 문제의 원인을 진단해야합니다.

그러나 실제로 nolock당신이 절대적으로 알고있는 쿼리를 추가 하는 것은 간단하고 간단한 읽기 전용 문제는 결코 문제를 일으키지 않는 것 같습니다 .

READ UNCOMMITTED고려할 수 있는 수준 에 대한 한 가지 대안 은 READ COMMITTED SNAPSHOT입니다. Jeff를 다시 인용 :

스냅 샷은 완전히 새로운 데이터 변경 추적 방법에 의존합니다. 약간의 논리적 변경보다 서버가 데이터를 물리적으로 다르게 처리해야합니다. 이 새로운 데이터 변경 추적 방법이 활성화되면 모든 데이터 변경의 복사본 또는 스냅 샷이 생성됩니다. 경합 발생시 라이브 데이터가 아닌 이러한 스냅 샷을 읽으면 더 이상 읽기에 공유 잠금이 필요하지 않으며 전체 데이터베이스 성능이 향상 될 수 있습니다.


13
저자는 커밋되지 않은 읽기 / 잠금 없음은 마지막 커밋 된 모든 데이터를 반환한다고 암시하는 것으로 보입니다. 커밋되지 않은 읽기는 커밋되지 않은 트랜잭션에서도 마지막으로 설정된 값을 반환합니다. 그렇다면 결과가 "몇 초 전"데이터를 검색하지 않습니다. 그것은 (또는 적어도 읽은 데이터를 쓴 트랜잭션이 롤백되는 경우) 존재하지 않거나 커밋되지 않은 데이터를 검색하는 것일 수 있습니다. 내가 착각 했니?
xr280xr

4
좋은 대답입니다. BTW, Oracle은 기본적으로 "스냅 샷"을 알고 있습니다. 아마도 Sql Server가 소개하기 수십 년 전에 알았을 것입니다. SQL Server를 시작할 때 매우 실망했으며 모든 동시성 문제가 "기본"잠금 메커니즘을 사용하여 해결되었음을 알았습니다. Oracle에서 "읽지 않은 커밋되지 않음"을 본 적이 없습니다. 그리고 실무자는 우주 비행사만큼 행복합니다.
Stefan Steinegger

13
READ UNCOMMITTED행을 두 번 읽거나 전체 행을 놓칠 수도 있습니다 . 읽는 동안 페이지 분할이 발생하면 전체 데이터 덩어리를 놓칠 수 있습니다. WITH(NOLOCK)결과의 정확성이 중요하지 않은 경우에만 사용해야합니다
Ian Boyd

8
때문에 @DanielNolan, 그 기사를 추천하기 것은 위험 제프 몰랐다 무엇을 그가하고 있었다 . 커밋되지 않은 읽기는 데이터 읽기에 적합합니다. 절대 수정되지 않습니다. 이것을 사용하여 쓰여질 테이블을 읽으려고 시도한다는 것은 실제로 롤백되는 것을 읽을 것임을 의미합니다 . 몇 초 전의 데이터를 읽는 것뿐만 아니라 .................................. ................... ‌‌ .................. ....
Pacerier

5
................................... 커밋 되지 않은 데이터를 읽고 있습니다 . 그것은 손상된 읽기의 정의입니다. 당신이가는 경우 그리고 결과에 따라 쓰기 그 커밋되지 않은 읽기, 당신은 실제로는 것 손상된 데이터를 작성합니다. 또한이 기사에서는 "웹 응용 프로그램에서 자란 MySQL은 SQL Server보다 비관적입니다." 사실은 아니지만 SQL Server는 기본적으로 읽기 커밋 된 수준에서 작동하지만 MySQL은 기본적으로 읽기 커밋되지 않은 수준 에서 5 단계 떨어진 반복 가능한 읽기에서 작동합니다 .
Pacerier

36

이것은 긴 삽입 쿼리의 진행 상황을 COUNT(*)보거나 대략 적인 추정 (예 : 또는 거칠기 SUM(*)) 등을 만드는 데 유용 할 수 있습니다 .

즉, 더티 읽기 쿼리가 반환하는 결과는 추정치로 간주하고이를 기반으로 중요한 결정을 내리지 않는 한 괜찮습니다.


36

내가 가장 좋아하는 유스 케이스 read uncommited는 트랜잭션 내부에서 발생하는 것을 디버깅하는 것입니다.

코드 라인을 단계별로 실행하는 동안 디버거에서 소프트웨어를 시작하면 트랜잭션이 열리고 데이터베이스가 수정됩니다. 코드가 중지 된 상태에서 쿼리 분석기를 열고 커밋되지 않은 읽기 격리 수준 을 설정하고 쿼리를 수행하여 진행 상황을 확인할 수 있습니다.

또한 장기 실행 프로 시저가 멈췄거나 데이터베이스를 올바르게 업데이트하는지 확인할 수 있습니다.

회사에서 지나치게 복잡한 저장 프로 시저를 만드는 것을 좋아한다면 좋습니다.


6
우리 회사는 지나치게 복잡한 저장 프로 시저를 만드는 것을 좋아합니다. 문제 해결을위한 좋은 아이디어입니다!
Brandon

22

어떤 상황에서는 더 빠를 수 있다는 장점이 있습니다. 단점은 결과가 잘못되어 (아직 커밋되지 않은 데이터가 반환 될 수 있음) 결과가 반복 가능하다는 보장이 없다는 것입니다.

정확성에 관심이 있다면 이것을 사용하지 마십시오.

자세한 내용은 MSDN에 있습니다 .

더티 읽기 또는 격리 수준 0 잠금을 구현합니다. 즉, 공유 잠금이 발행되지 않고 독점 잠금이 적용되지 않습니다. 이 옵션을 설정하면 커밋되지 않은 데이터 또는 더티 데이터를 읽을 수 있습니다. 트랜잭션이 끝나기 전에 데이터의 값을 변경하고 행이 데이터 세트에 나타나거나 사라질 수 있습니다. 이 옵션은 트랜잭션의 모든 SELECT 문에있는 모든 테이블에서 NOLOCK을 설정하는 것과 동일한 효과를 갖습니다. 이것은 네 가지 격리 수준 중에서 가장 제한이 적습니다.


이것이 쿼리 속도에 어떤 영향을 미칩니 까?
Kip Real

11
@Kip- select명령문은 다른 트랜잭션에 의해 독점적으로 잠긴 리소스에 대한 공유 잠금을 얻기 위해 기다릴 필요가 없습니다.
Jarrod Dixon

15

언제 사용할 수 READ UNCOMMITTED있습니까?

엄지 손가락의 법칙

양호 : 지속적으로 변화하는 총계를 보여주는 큰 집계 보고서.

위험 : 거의 모든 것.

좋은 소식은 읽기 전용 대부분의 보고서가에 빠지게한다는 것입니다 좋은 종류.

자세한 세부 사항...

그것을 사용하십시오 :

  • 현재 비 정적 데이터 (예 : 연도 별 매출)에 대한 거의 모든 사용자 대면 집계 보고서 오차 한계 (0.1 % 미만일 수 있음)가 발생하여 오차 입력과 같은 다른 불확실성 요소 나 정확히 1 분에서 정확히 데이터가 기록 될 때의 무작위성보다 훨씬 낮습니다.

SSRS와 같은 비즈니스 인텔리전스 부서가 수행 할 대부분의 작업이 여기에 해당합니다. 물론, $ 표시가 앞에있는 것은 예외입니다. 많은 사람들이 고객에게 서비스를 제공하고 그 돈을 창출하는 데 필요한 관련 핵심 메트릭스에 적용되는 것보다 훨씬 열성적인 돈을 설명합니다. (저는 회계사를 비난합니다).

위험 할 때

  • 상세 수준으로 내려가는 모든 보고서. 세부 사항이 필요한 경우 일반적으로 모든 행이 결정과 관련이 있음을 의미합니다. 실제로, 작은 부분 집합을 차단하지 않고 당길 수 없다면 그것이 현재 편집되고있는 좋은 이유 일 수 있습니다.

  • 과거 데이터. 실질적인 차이는 거의 없지만 사용자는 끊임없이 변화하는 데이터가 완벽 할 수는 없다는 것을 이해하지만 정적 데이터에 대해서는 동일하게 느끼지 않습니다. 더티 리딩은 여기서 아프지 않지만 더블 리딩은 때때로 일어날 수 있습니다. 어쨌든 정적 데이터에 대한 차단이 없어야하는 이유는 무엇입니까?

  • 쓰기 기능이있는 응용 프로그램을 공급하는 거의 모든 것.

OK 시나리오에서도 OK가 아닙니다.

  • 큰 단일 트랜잭션을 사용하는 응용 프로그램이나 업데이트 프로세스가 있습니까? 당신이보고있는 많은 기록을 제거한 다음 다시 삽입하는 것? 이 경우 실제로 NOLOCK해당 테이블에서 아무것도 사용할 수 없습니다 .

보고서에 대한 좋은 지적. 사실 내 생각에 떠오른 첫 번째 아이디어는 read uncommitted사용자가 데이터 정확도가 그렇게 중요하지 않은 UI 그리드를 볼 때 웹 응용 프로그램에 사용해야한다는 것 입니다. 사용자는 단지 어떤 레코드가 있는지, 그리고 페이징, 정렬 및 필터링과 같은 간단한 개요를 원합니다. 사용자가 편집 버튼을 클릭 할 때만 더 엄격한 격리 수준으로 최신 레코드를 읽으려고합니다. 성능 측면에서 이러한 접근 방식이 더 좋을까요?
JustAMartin

예, 그것이 합리적이라고 생각합니다. 더 중요한 문제는 편집 버튼을 눌렀을 때와 제출 시간 사이에 다른 사람이 데이터를 변경하지 않았 음을 확인하는 것입니다. 같은 데이터를 가져 오는 트랜잭션을 시작하여 처리 할 수 ​​있습니다 select item from things with (UPDLOCK). 빠른 시간 초과를 설정하면 잠금을 빨리 얻지 못하면 사용자에게 편집 중임을 알려줍니다. 사용자뿐만 아니라 개발자로부터도 안전하게 보호 할 수 있습니다. 여기서 문제는 시간 초과와 UI에서 시간 초과를 처리하는 방법에 대해 생각해야한다는 것입니다.
Adamantish

6

보고와 관련하여 Google은 모든보고 쿼리에서이 보고서를 사용하여 쿼리가 데이터베이스를 다운시키는 것을 방지합니다. 우리는 마이크로 초 단위의 데이터가 아닌 과거 데이터를 가져 오기 때문에 그렇게 할 수 있습니다.


4

소스가 변경 될 가능성이 거의없는 상황에서는 READ_UNCOMMITTED를 사용하십시오.

  • 히스토리 데이터를 읽을 때. 예를 들어 이틀 전에 발생한 일부 배포 로그.
  • 메타 데이터를 다시 읽을 때 메타 데이터 기반 애플리케이션.

페치 조작 중에 소스가 변경 될 수 있음을 알고있을 때 READ_UNCOMMITTED를 사용하지 마십시오.


1
나는 그 반대가 적용된다고 생각한다. 먼저 정적 데이터는 블록없이 잘 읽어야합니다. 이 경우 않습니다 다음 블록 당신은 지금 수정에 중요한 매달려 트랜잭션 문제가있다 발견했습니다. 또한 사용자는 작년의 연례 보고서를 위해 인쇄 한 모든 소수점 이하 자릿수와 일치 할 것으로 예상합니다. 그들은 일반적으로 자신들이 알고있는 것과 동일한 흐름이 일정하다고 생각하지 않습니다. 이것은 상세하고 매우 시간에 민감하거나 재무보고에 적합하지 않지만 1000에 1 입력 오류가 허용되는 경우에도 마찬가지입니다 READ UNCOMMITTED.
Adamantish

TLDR : 데이터가 변경되지 않으면 어쨌든 블록이 없으므로 COMMUNTED를 읽을 필요가 없습니다. 잘못되어 변경되는 경우 사용자가 예상보다 더 더러운 데이터를 얻지 못하게 차단하는 것이 좋습니다.
Adamantish

예, 저는 @Adamantish에 동의하는 경향이 READ UNCOMMITTED있습니다. 데이터를 적극적으로 사용하고 서버에서 부하를 줄이려고 할 때 대부분의 이점을 누릴 수 있습니다 . 부주의하게 악용되는 일부 사용자 때문에 데이터 그리드가있는 웹 페이지의 '새로 고침'버튼을 클릭합니다. 동시에 많은 레코드를 보는 사용자는 데이터가 약간 오래되었거나 부분적으로 업데이트 된 경우 크게 신경 쓰지 않습니다. 사용자가 레코드를 편집하려고 할 때만 가장 정확한 데이터를 제공 할 수 있습니다.
JustAMartin

2

이렇게하면 더티 읽기가 이루어지고 아직 커밋되지 않은 트랜잭션이 표시됩니다. 이것이 가장 확실한 대답입니다. 나는 단지 당신의 독서 속도를 높이기 위해 이것을 사용하는 것이 좋지 않다고 생각합니다. 좋은 데이터베이스 디자인을 사용하는 경우 다른 방법이 있습니다.

일어나지 않는 것을 주목하는 것도 흥미 롭습니다. READ UNCOMMITTED는 다른 테이블 잠금 만 무시하지 않습니다. 또한 자체 잠금을 발생시키지 않습니다.

큰 보고서를 생성하거나 크고 복잡한 SELECT 문을 사용하여 데이터베이스에서 데이터를 마이그레이션하는 것을 고려하십시오. 이로 인해 트랜잭션 기간 동안 공유 잠금이 공유 테이블 잠금으로 에스컬레이션 될 수 있습니다. 다른 트랜잭션은 테이블에서 읽을 수 있지만 업데이트는 불가능합니다. 프로덕션이 완전히 중지 될 수 있으므로 프로덕션 데이터베이스 인 경우 나쁜 아이디어 일 수 있습니다.

READ UNCOMMITTED를 사용하는 경우 테이블에 공유 잠금을 설정하지 않습니다. 일부 새 트랜잭션에서 결과를 얻거나 데이터가 삽입 된 테이블 및 SELECT 트랜잭션이 읽은 시간에 따라 달라질 수 있습니다. 예를 들어 페이지 분할이 발생하는 경우 동일한 데이터를 두 번 얻을 수도 있습니다 (데이터 파일의 다른 위치로 데이터가 복사 됨).

따라서 SELECT를 수행하는 동안 데이터를 삽입 할 수있는 것이 매우 중요한 경우 READ UNCOMMITTED가 의미가있을 수 있습니다. 보고서에 약간의 오류가있을 수 있지만 결과를 선택하는 동안 수백만 행을 기반으로하고 그 중 몇 개만 업데이트되는 경우 "충분히 좋을 수 있습니다"라는 것을 고려해야합니다. 행의 고유성이 보장되지 않으므로 트랜잭션이 모두 실패 할 수도 있습니다.

더 좋은 방법은 SNAPSHOT ISOLATION LEVEL을 사용하는 것이지만이를 사용하려면 응용 프로그램에서 약간의 조정이 필요할 수 있습니다. 이에 대한 한 가지 예는 응용 프로그램이 다른 사용자가 읽지 못하고 UI에서 편집 모드로 들어 가지 못하도록 행에 독점 잠금을 설정하는 경우입니다. SNAPSHOT ISOLATION LEVEL에는 상당한 성능 저하가 있습니다 (특히 디스크에서). 그러나 문제에 하드웨어를 던져서이를 극복 할 수 있습니다. :)

데이터웨어 하우스에 데이터를보고하거나로드하는 데 사용할 데이터베이스 백업 복원을 고려할 수도 있습니다.


0

기존 테이블에 대한 업데이트가없고 다른 테이블에 대한 fk가없는 삽입 전용 감사 테이블과 같은 간단한 테이블에 사용할 수 있습니다. 인서트는 롤백 가능성이 거의없는 간단한 인서트입니다.


-7

나는 항상 지금 커밋되지 않은 읽기를 사용합니다. 최소한의 문제로 빠릅니다. 다른 격리를 사용하면 거의 항상 일부 차단 문제가 발생합니다.

자동 증분 필드를 사용하고 인서트에 약간 더주의를 기울이는 한 벌금 문제에 대해서는 작별 인사를 할 수 있습니다.

COMMUNCOMMITED READ로 오류를 만들 수 있지만 솔직히 말하면 인서트가 완전한 증거인지 확인하는 것은 매우 쉽습니다. 선택의 결과를 사용하는 삽입 / 업데이트는주의해야합니다. (READ COMMITTED를 사용하거나 더티 판독으로 인해 문제가 발생하지 않도록하십시오)

Dirty Reads (특히 큰 보고서의 경우)로 이동하면 소프트웨어가 더 부드럽게 실행됩니다.


6
이것은 매우 부정확하며 nolock으로 발생할 수있는 문제의 표면에만 닿습니다. 페이지가 분할되거나 조인이 실패 할 수 있으며 존재하지 않는 데이터를 읽거나 데이터를 복제 할 수 있습니다. 이를 완벽하게 사용하는 방법은 없습니다.이 격리 수준에서 어떤 정확도를 신뢰할 수는 없습니다. 커밋 된 스냅 샷은 덜 위험한 "가짜 만병 통치약"입니다
Mark Sowul

@MarkSowul이 답변의 하향 투표는 나에게 불공평 한 것 같습니다. @Clive는 Committed삽입 및 업데이트 를 위해 전환하기로 결정 했습니다. 다른 문제에 관해서도 그는 자동 증가 키를 사용하여 언급 할 때 페이지 분할 문제에 대한 인식을 보여주었습니다. 나는 단지 인간에 의해 읽힌 거의 모든 생방송보고가 소수점 이하 자릿수에 약간의 불일치를 허용 할 수 있다는 것에 동의합니다. 자세한 목록이나 머신 읽기 및 변형이 필요한 데이터에 대한 이야기가 다르다는 것에 동의합니다.
Adamantish

1
이 의견은 또한 nolock과 함께 발생할 수있는 문제에 대한 완전한 이해가 부족함을 보여줍니다. "마지막 소수점 자리의 약간의 차이"는 거의 다루지 않습니다. "삽입 / 업데이트에 커밋 된 읽기 전용 사용"을 터치해도 일반적인 조언으로 잘못되었습니다 ( "존재하지 않는 레코드 삽입"인 경우 어떻게됩니까?). 어쨌든 "[미 확약 읽기]가 가장 적은 문제로 빠르다"는 것은 잘못된 것입니다.
Mark Sowul

기록을 위해, 나는 당신의 대답 Adamantish에 동의합니다 : 대략 정확한 집계 및 다른 것.
Mark Sowul
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.