문제

나는 낙관적 인 잠금과 비관적 잠금의 차이점을 이해합니다. 이제 누군가가 일반적으로 둘 중 하나를 사용할 때 누군가 나에게 설명 할 수 있습니까?

그리고이 질문에 대한 답이 저장된 절차를 사용하여 쿼리를 수행하는지 여부에 따라 변경됩니까?

그러나 낙관적은 "읽는 동안 테이블을 잠그지 말라"는 것을 의미하며 비관적은 "읽는 동안 테이블을 잠그십시오"를 의미합니다.

도움이 되었습니까?

해결책

낙관적 잠금 레코드를 읽고 버전 번호를 기록한 전략입니다 (이를 수행하는 다른 방법에는 날짜, 타임 스탬프 또는 체크섬/해시가 포함됩니다). 레코드를 작성하기 전에 버전이 변경되지 않았는지 확인하십시오. 레코드를 다시 작성하면 버전의 업데이트를 원자체인지 확인합니다. (즉, 버전을 확인하고 레코드를 디스크에 작성할 때간에 업데이트되지 않았습니다).

레코드가 더러워지면 (예 : 다른 버전과 다른 버전) 거래를 중단하고 사용자가 다시 시작할 수 있습니다.

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

비관적 인 잠금 당신이 그것을 끝낼 때까지 독점적으로 사용하기 위해 레코드를 잠글 때입니다. 그것은 낙관적 잠금보다 훨씬 나은 무결성을 가지고 있지만 응용 프로그램 설계에주의를 기울여야합니다. 교착 상태. 비관적 잠금을 사용하려면 데이터베이스에 직접 연결해야합니다 (일반적으로 경우에 따라 두 계층 클라이언트 서버 응용 프로그램) 또는 연결과 독립적으로 사용할 수있는 외부에서 사용 가능한 트랜잭션 ID.

후자의 경우 TXID로 트랜잭션을 열고 해당 ID를 사용하여 다시 연결합니다. DBMS는 잠금 장치를 유지하고 TXID를 통해 세션을 다시 선택할 수 있습니다. 이것은 2 단계 커밋 프로토콜을 사용한 분산 거래 (예 : XA 또는 com+ 트랜잭션) 일하다.

다른 팁

많은 충돌을 기대하지 않을 때 낙관적 잠금이 사용됩니다. 정상적인 운영 비용은 저렴하지만 충돌이 발생하면 거래가 중단 될 때 더 높은 가격을 지불 할 것입니다.

비관적 잠금은 충돌이 예상 될 때 사용됩니다. 동기화를 위반하는 트랜잭션은 단순히 차단됩니다.

적절한 잠금 메커니즘을 선택하려면 읽기 및 쓰기의 양을 추정하고 그에 따라 계획해야합니다.

낙관적은 읽는 동안 아무것도 변하지 않을 것이라고 가정합니다.

비관론은 무언가가 될 것이라고 가정하고 그것을 잠그는다 고 가정합니다.

데이터를 완벽하게 읽는 것이 필수적이지 않은 경우 낙관적으로 사용하십시오. 당신은 이상한 '더티'를 읽을 수 있지만 교착 상태 등을 초래할 가능성이 훨씬 적습니다.

대부분의 웹 애플리케이션은 더러운 판독 값으로 괜찮습니다. 드문 경우에는 데이터가 다음 재 장전이 정확히 집계하지 않습니다.

정확한 데이터 운영 (많은 금융 거래에서와 같이)의 경우 비관적 사용을 사용하십시오. 부담이없는 변경없이 데이터를 정확하게 읽어야합니다. 추가 잠금 오버 헤드는 그만한 가치가 있습니다.

아, 그리고 Microsoft SQL Server는 기본적으로 페이지 잠금 장치 - 기본적으로 당신이 읽고있는 행과 어느 쪽이든 몇 가지 쪽입니다. 행 잠금은 더 정확하지만 훨씬 느립니다. 읽는 동안 교착 상태를 피하기 위해 거래를 읽을 수 있거나 잠깐 동안 거래 할 가치가 있습니다.

이미 말한 것 외에도 낙관적 잠금은 예측 가능성을 희생시키면서 동시성을 향상시키는 경향이 있다고 말해야합니다. 비관적 잠금은 동시성을 줄이는 경향이 있지만 더 예측 가능합니다.

당신은 당신의 돈을 지불합니다

비관적 인 잠금이 더 나은 선택이 될 때 한 가지 더 생각할 것입니다.

낙관적 잠금의 경우 데이터 수정에 모든 참가자는 이러한 종류의 잠금을 사용하는 데 동의해야합니다. 그러나 누군가가 버전 열을 돌보지 않고 데이터를 수정하면 낙관적 잠금에 대한 전체 아이디어를 망칠 것입니다.

기본적으로 가장 인기있는 두 가지 답변이 있습니다. 그만큼 첫 번째 기본적으로 말합니다

낙관론은 세션의 데이터베이스 연결을 반드시 유지하지는 않는 반면 비관적 잠금은 당신이 끝날 때까지 독점적으로 사용하기 위해 레코드를 잠그는 경우 3 계층 아키텍처가 필요합니다. 낙관적 잠금보다 훨씬 나은 무결성을 가지고 있습니다. 데이터베이스에 직접 연결해야합니다.

또 다른 대답은

낙관적 (버전)은 잠금이 없기 때문에 더 빠르지 만 경합이 높을 때 (비관적) 잠금은 더 잘 수행되며, 작업을 폐기하지 않고 시작하는 것이 아니라 다시 시작하는 것이 좋습니다.

또는

낙관적 잠금은 드문 충돌이있을 때 가장 잘 작동합니다

그것을 넣을 때 이 페이지에서.

"유지 관리"가 "낮은 충돌"과 어떻게 관련되어 있는지 설명하기 위해 대답을 만들었습니다.

어떤 전략이 자신에게 가장 적합한 지 이해하려면 DB가 초당 거래에 대해 생각하지 않고 단일 거래 기간을 생각해보십시오. 일반적으로 Trasnaction을 열고, 수행하고, 거래를 닫습니다. 이것은 ANSI가 생각했던 짧고 고전적인 거래입니다. 그러나 많은 고객이 동시에 같은 방/좌석을 예약하는 티켓 예약 시스템을 어떻게 구현합니까?

제안을 탐색하고 많은 가용 옵션과 현재 가격으로 양식을 작성하십시오. 시간이 많이 걸리고 옵션이 쓸모 없게 될 수 있습니다. 양식을 작성하기 시작한 모든 가격이 유효하지 않은 양식을 작성하고 "동의 한"버튼을 누르기 시작했습니다. 모든 가격을 변경하면 새로운 가격으로 다시 시작해야합니다.

대신 읽을 때 모든 옵션을 잠글 수 있습니다. 이것은 비관적 시나리오입니다. 당신은 그것이 왜 짜증나는지 알 수 있습니다. 단순히 예약을 시작하고 담배를 피우는 단일 광대가 시스템을 가져올 수 있습니다. 그가 끝나기 전에 아무것도 예약 할 수 없습니다. 현금 흐름은 0으로 떨어집니다. 그렇기 때문에 낙관적 예약이 실제로 사용됩니다. 너무 오래 걸리는 사람들은 예약을 더 높은 가격으로 다시 시작해야합니다.

이 낙관적 접근 방식에서는 읽은 모든 데이터를 기록해야합니다 ( 내 반복 읽기)) 그리고 귀하의 데이터 버전으로 커밋 포인트에 오십시오 (현재 가격이 아닌이 견적에 표시 한 가격으로 주식을 사고 싶습니다). 이 시점에서 ANSI 트랜잭션이 생성되어 DB를 잠그고 아무것도 변경되지 않은지 확인하고 작업을 수행/중단합니다. IMO, 이것은 효과적인 에뮬레이션입니다 MVCC, 또한 낙관적 CC와 관련이 있으며 중단시 거래가 다시 시작된다고 가정합니다. 즉, 새로운 예약을 할 것입니다. 여기서 거래에는 인간 사용자 결정이 포함됩니다.

MVCC를 수동으로 구현하는 방법을 이해하지 못하고 다시 시작 옵션을 사용하여 장기 거래가 주제를 이해하는 열쇠라고 생각합니다. 내가 어디서나 틀렸다면 나를 수정하십시오. 내 대답은 동기를 부여 받았다 이 Alex Kuznecov 장.

대부분의 경우 낙관적 잠금이 더 효율적이며 더 높은 성능을 제공합니다. 비관적 인 잠금과 낙관적 잠금을 선택할 때 다음을 고려하십시오.

  • 비관적 잠금은 많은 업데이트가 있고 사용자가 동시에 데이터를 업데이트하려고 할 가능성이 높으면 유용합니다. 예를 들어, 각 운영이 한 번에 많은 수의 기록을 업데이트 할 수있는 경우 (은행은 매월 말에 모든 계정에이자 수입을 추가 할 수 있음) 두 개의 응용 프로그램이 동시에 그러한 운영을 실행하는 경우 충돌이 발생합니다. .

  • 비관적 잠금은 또한 자주 업데이트되는 작은 테이블을 포함하는 응용 프로그램에서 더 적합합니다. 이러한 소위 핫스팟의 경우, 충돌은 낙관적 인 잠금이 충돌 거래를 롤백하는 데 낭비되는 노력을 낭비 할 가능성이 높습니다.

  • 낙관적 잠금은 충돌 가능성이 매우 낮 으면 유용합니다. 레코드가 많지만 비교적 적은 사용자가 많거나 업데이트가 거의없고 대부분 읽기 유형 작업이 있습니다.

낙관적 잠금의 사용 사례 중 하나는 응용 프로그램이 데이터베이스를 사용하여 스레드 / 호스트 중 하나가 작업을 '주장'할 수 있도록하는 것입니다. 이것은 정기적으로 나에게 유용한 기술입니다.

내가 생각할 수있는 가장 좋은 예는 데이터베이스를 사용하여 구현 된 작업 대기열에 대한 것입니다. 여러 스레드가 동시에 작업을 주장합니다. 작업에 상태가 '사용 가능한', '주장 된', '완료'가있는 경우, DB 쿼리는 "set status = 'halding'where athration = '사용 가능한'과 같은 것을 말할 수 있습니다. 여러 스레드가 이러한 방식으로 상태를 변경하려고하면, 첫 번째 스레드를 제외한 모든 스레드는 더러운 데이터로 인해 실패합니다.

이것은 낙관적 잠금 만 포함하는 사용 사례입니다. 따라서 "많은 충돌을 기대하지 않을 때 낙관적 잠금이 사용됩니다"라는 대안으로 충돌을 예상하지만 정확히 하나의 트랜잭션이 성공하기를 원하는 경우에도 사용할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top