비관적 잠금보다 낙관적 잠금이 더 빠른 이유는 무엇입니까?


9

두 가지 유형의 잠금은 현재 프로세스가 다른 프로세스에서 사용중인 경우 프로세스가 레코드의 올바른 사본을 대기하도록합니다. 비관적 잠금의 경우 잠금 메커니즘은 DB 자체 (기본 잠금 개체)에서 비롯된 반면, 낙관적 잠금의 경우 잠금 메커니즘은 레코드가 "stale"인지 여부를 확인하는 타임 스탬프와 같은 일종의 행 버전 관리 형식입니다.

그러나 두 번째 프로세스는 두 번째 프로세스를 중단시킵니다. 그래서 나는 묻습니다 : 왜 낙관적 잠금이 일반적으로 비관적 잠금보다 빠르거나 우수한 것으로 간주됩니까? 그리고 비관론이 낙관론보다 선호되는 사용 사례가 있습니까? 미리 감사드립니다!


5
명명에 매우 간단한 설명이 있습니다. 낙관적 잠금 가능성이 낮을 때 낙관적 잠금이 잘 작동합니다. 우리는 여러 프로세스의 상호 작용에 대해 낙관적입니다. 비관적 잠금은 잠금 충돌 가능성이 높을 때 잘 작동합니다. 우리는 여러 프로세스의 상호 작용에 대해 비관적입니다. 둘 다 반대가 더 적절한 곳에서 차선책으로 수행됩니다.
Mark Storey-Smith

작업 부하에 따라 낙관적 잠금이 비관적 잠금보다 빠르거나 빠를 수 있습니다.
AK

답변:


8

의 중복 질문 :

/programming/129329/optimistic-vs-pessimistic-locking

위 링크에서 답변 복사 / 붙여 넣기 :

낙관적 잠금은 레코드를 읽고 버전 번호를 기록한 후 레코드를 다시 쓰기 전에 버전이 변경되지 않았는지 확인하는 전략입니다. 레코드를 다시 쓰면 버전의 업데이트를 필터링하여 최신 상태인지 확인합니다. (즉, 버전을 확인하고 레코드를 디스크에 쓸 때 사이에 업데이트되지 않았습니다) 한 번에 버전을 업데이트하십시오.

레코드가 더러 우면 (즉, 다른 버전과 다름) 트랜잭션을 중단하고 사용자가 다시 시작할 수 있습니다.

이 전략은 세션의 데이터베이스에 대한 연결을 반드시 유지할 필요가없는 대용량 시스템 및 3 계층 아키텍처에 가장 적합합니다. 이 상황에서는 연결이 풀에서 이루어 지므로 클라이언트가 실제로 데이터베이스 잠금을 유지할 수 없으며 한 액세스에서 다음 액세스로 동일한 연결을 사용하지 않을 수 있습니다.

비관적 잠금은 레코드가 끝날 때까지 독점 사용을 위해 레코드를 잠그는 것입니다. 낙관적 잠금보다 무결성이 훨씬 뛰어나지 만 교착 상태를 피하려면 응용 프로그램 디자인에주의해야합니다. 비관적 잠금을 사용하려면 일반적으로 2 계층 클라이언트 서버 응용 프로그램에서와 같이 데이터베이스에 직접 연결하거나 연결과 독립적으로 사용할 수있는 외부에서 사용 가능한 트랜잭션 ID가 필요합니다.

후자의 경우 TxID로 트랜잭션을 연 다음 해당 ID를 사용하여 다시 연결합니다. DBMS는 잠금을 유지하고 TxID를 통해 세션을 다시 선택할 수 있습니다. 이는 2 단계 커밋 프로토콜 (예 : XA 또는 COM + 트랜잭션)을 사용하는 분산 트랜잭션이 작동하는 방식입니다.

편집 (성능 질문에 대한 추가 정보 추가) :

현명한 성능은 환경에 따라 다릅니다. 다음 사항을 고려하여 결정하십시오.

대부분의 상황에서 동시성으로 인해 낙관적입니다. 그러나 RDBMS 및 환경에 따라 성능이 다소 떨어질 수 있습니다. 일반적으로 낙관적 잠금을 사용하면 값을 어딘가에 행 버전 화해야합니다.

예를 들어 MS SQL Server를 사용하면 TempDB로 이동하고 열의 끝에 12-14 바이트 사이에 추가됩니다. Snapshot Isolation과 같은 격리 수준으로 낙관적 잠금을 설정하면 조각화가 발생할 수 있으며 마지막에 행에 추가 데이터가 추가되어 페이지가 거의 꽉 차서 페이지가 분할 될 수 있으므로 채우기 비율을 조정해야합니다. 당신의 성능. TempDB가 최적화되지 않은 경우 빠르지 않습니다.

체크리스트는 다음과 같습니다.

  • -행 버전 관리 형식을 처리하기에 충분한 IO / 리소스가 있습니까? 그렇지 않은 경우 오버 헤드가 추가됩니다. 그렇다면 쓰기를 위해 데이터를 잠그는 동안 데이터를 자주 읽는 경우 읽기와 쓰기에서 동시성이 향상됩니다 (쓰기는 여전히 쓰기를 차단하지만 읽기는 더 이상 쓰기를 차단하지 않으며 그 반대도 마찬가지 임)
  • -코드가 교착 상태에 취약하거나 잠금이 발생합니까? 긴 잠금 또는 많은 교착 상태가 발생하지 않으면 낙관적 잠금의 추가 오버 헤드로 인해 속도가 빨라지지는 않지만 대부분의 경우 여기서는 밀리 초를 말합니다.
  • -DB가 크거나 (또는 ​​매우 제한된 하드웨어에있는) RDBMS에 따라 데이터 페이지가 거의 가득 찬 경우 주요 페이지 분할 및 데이터 조각화가 발생할 수 있으므로 전원을 켠 후에 다시 색인화를 고려해야합니다.

이것들은이 문제에 대한 나의 생각이며, 지역 사회로부터 더 많은 것을들을 수 있도록 열려 있습니다.


감사합니다 @Ali Razeghi (+1)-dba.se 가이 질문에 더 적합한 장소라고 생각합니다. 또한 이것은 훌륭한 답변이지만 성능에 대한 나의 질문에는 대답하지 않습니다 (하나가 다른 것보다 빠를 때). 다시 감사합니다!
Mara

안녕 마라, 그게 좋은 지적이야. 나는 대답을 확장했다. 감사.
Ali Razeghi

11

낙관적 잠금을 오해합니다.

낙관적 잠금으로 인해 트랜잭션이 서로를 기다리지 않습니다.

낙관적 잠금으로 인해 트랜잭션이 실패 할 수 있지만 "잠금"을 수행하지 않아도됩니다. 낙관적 잠금으로 인해 트랜잭션이 실패하면 사용자는 다시 시작해야합니다. "낙관적"이라는 단어는 바로 이러한 이유로 트랜잭션이 실패하게하는 조건이 매우 예외적으로 발생할 것이라는 기대에서 정확히 유래합니다. "최적"잠금은 "어쨌든 필요하지 않기 때문에 실제 잠금을 사용하지 않을 것입니다. 그것이 틀렸다면 필연적 인 실패를 받아 들일 것입니다."라는 접근 방식입니다.


1

데이터베이스 관점에서 실제로 잠금이 없기 때문에 일반적으로 낙관적 잠금이 더 빠릅니다. 버전 열 (또는 ora_rowscn과 같은 의사 열)을 존중할지 여부는 전적으로 응용 프로그램에 달려 있습니다. 일반적으로 동일한 데이터베이스에 많은 응용 프로그램이 연결되어 있으므로 db는 공유 리소스가되고 중단되면 모든 클라이언트에 영향을 미칩니다.

낙관적 잠금 전략을 사용하면 클라이언트 측에서 '매달려'발생하며 다른 사람에게는 영향을 미치지 않습니다.

그러나 레코드가 자주 업데이트되면 낙관적 잠금의 경우 레코드를 너무 여러 번 다시 읽게되어 낙관적 전략의 이점을 최대한 활용할 수 없게됩니다.

나는 두 접근법의 우월성에 대해서는 동의하지 않는다. 둘 다 오용 될 수 있습니다. 비관적 인 경우보다 위험하기 때문에 오류가 발생하기 쉽습니다 .DB 수준에서 잠금이 발생합니다. RDMS에 따라 잠금 상태 (잠금 에스컬레이션)에 대한 제어 권한이 없을 수 있으므로 잠금 순서를 수동으로 처리해야합니다.


재미있는 점 a1ex07, 쓰기는 항상 다른 쓰기를 차단하므로 최적화 잠금은 여전히 ​​잠금을 포함합니다.
Ali Razeghi

아닙니다. 그것이 "빠른"이유입니다.
Erwin Smout

Oracle의 경우에는 가능하지만 MS SQL Server의 경우 기본적으로 '읽기 커밋 된'격리 수준을 사용하므로 낙관적 잠금을 사용하면 리더와 기록기 스레드가 동시에 작동 할 수 있지만 쓰기는 차단 스레드가 커밋 될 때까지 쓰기를 차단합니다.
Ali Razeghi

@Ali Razeghi : 당신의 요점을 잘 모르겠습니다. 읽기 커밋 된 라이터가있는 SQLServer에서`READ_COMMITTED_SNAPSHOT`이 켜져 있지 않으면 기본적으로 리더를 차단합니다. 낙관적 잠금은 db 리소스 (행 / 페이지 / 테이블)에 대한 잠금이 아니라 버전이 예상과 일치하지 않는 경우 데이터베이스를 사용하여 레코드를 업데이트하지 않는 모든 응용 프로그램 간의 일종의 동의입니다.
a1ex07

1
@Eamon Nerbonne : '작가는 독자를 차단하지 않습니다'에 대해 말했습니다 ... "작가는 작가를 차단하거나 차단하지 않습니다"에 대해 언급 한 곳은 어디입니까?
a1ex07

0

낙관적 잠금은 동시 트랜잭션이 서로 영향을 미치지 않고 완료 될 수 있다고 가정합니다. 따라서 트랜잭션을 수행하는 동안 잠금이 적용되지 않기 때문에 낙관적 잠금이 더 빠릅니다. 동시성 문제가 치료되지 않는 원인이되는 예방입니다. 트랜잭션은 다른 트랜잭션이 데이터를 수정하지 않은 데이터를 확인합니다 (세 가지 방법으로 데이터 세트, 타임 스탬프 데이터 유형, 이전 값 및 새 값 확인). 수정하는 경우 트랜잭션이 롤백됩니다.

비관적 잠금은 동시 트랜잭션이 서로 충돌한다고 가정하므로 잠금이 필요하며 트랜잭션 관리의 ISOLATION 수준 (읽지 않은 커밋되지 않은 읽기, 커밋 된 읽기, 반복 가능한 읽기 및 직렬화 가능)을 지정하여 이루어지며 잠금을 획득하여 동시성 문제를 해결합니다. 잠금은 공유 리소스 또는 개체 (테이블, 데이터 행, 데이터 블록, 캐시 된 항목, 연결 및 전체 시스템)를 보호하는 역할을합니다. 공유 잠금, 업데이트 잠금, 삽입 잠금, 독점 잠금, 트랜잭션 잠금, DML 잠금, 스키마 잠금 및 백업 복구 잠금과 같은 여러 유형의 잠금이 있습니다.

더 많은 아이디어를 얻기 위해


-3

비관적 잠금이 낙관적 이라기보다 느리거나 낙관적이라고 더 빠르다는 것은 거짓입니다. 이 부적절한 사고 방식을 설명하기위한 하나의 고전적인 쿼리는 다음과 같이 다른 RDBMS에 대해 집계하는 것입니다.

SELECT COUNT(*) FROM atable

기본적으로 낙관적 인 접근 방식을 지원하는 RDBMS에서이 쿼리에 걸리는 시간은 기본적으로 비관적 인 잠금을 가진 사람들보다 훨씬 중요합니다.

예를 들어 내 PC에서 동일한 쿼리는 SQL Server에서 27ms, PostGreSQL에서 109가 걸립니다 ...

MVCC 행의 데드 버전을 읽는 데 필요한 추가 오버 헤드와 집계에서 고스트 레코드를 계산하지 않으면 비관적 인 비용이 추가되지 않습니다!


4
DBMS 동시성 제어 접근 방식은 낙관적 / 비관적 잠금과 직교하며 두 개의 서로 다른 DBMS에서 쿼리 실행 시간을 비교하는 것은 잘못된 것입니다.
mustaccio

SQL Server는 두 가지 잠금 모드를 수행 할 수 있기 때문에 사용자 동시성 접근 방식에서 실제 경고를 수행하여이를 쉽게 비교할 수 있습니다.
user7370003
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.