낙관적 vs.비관적 잠금
낙관적 잠금과 비관적 잠금의 차이를 이해합니다.그럼 일반적으로 둘 중 하나를 언제 사용하는지 누가 설명해주실 수 있나요?
그리고 이 질문에 대한 답은 제가 쿼리를 수행하기 위해 저장 프로시저를 사용하고 있는지 여부에 따라 달라지는가요?
그러나 단지 확인하기 위해, 낙관적인 것은 "책 읽는 동안 테이블을 잠그지 말라"는 의미이고 비관적인 것은 "책 읽는 동안 테이블을 잠그라"는 의미입니다.
낙관적 잠금은 레코드를 읽고 버전 번호(다른 방법에는 날짜, 타임스탬프 또는 체크섬/해시가 포함됨)를 기록하고 레코드를 다시 쓰기 전에 버전이 변경되지 않았는지 확인하는 전략입니다.레코드를 다시 쓸 때는 버전의 업데이트를 필터링하여 원자성인지 확인합니다.(즉, 버전을 확인하고 디스크에 레코드를 쓸 때 사이에 업데이트되지 않았습니다.) 그리고 한 번에 버전을 업데이트합니다.
레코드가 더러우면(즉, 레코드와 다른 버전) 트랜잭션을 중단하고 사용자가 다시 시작할 수 있습니다.
이 전략은 세션에서 데이터베이스에 대한 연결을 반드시 유지할 필요가 없는 대용량 시스템 및 3계층 아키텍처에 가장 적합합니다.이 상황에서 클라이언트는 풀에서 연결을 가져옴에 따라 실제로 데이터베이스 잠금을 유지할 수 없으며 한 액세스에서 다음 액세스로의 연결을 동일하게 사용하지 않을 수도 있습니다.
비관적 잠금은 레코드를 완료할 때까지 독점적으로 사용하기 위해 레코드를 잠글 때를 말합니다.이것은 낙관적인 잠금보다 훨씬 더 나은 무결성을 가지고 있지만 데드락을 피하기 위해서는 응용 프로그램 설계에 주의해야 합니다.비관적 잠금을 사용하려면 일반적으로 2계층 클라이언트 서버 응용프로그램의 경우처럼 데이터베이스에 직접 연결하거나 연결과 독립적으로 사용할 수 있는 외부에서 사용 가능한 트랜잭션 ID가 필요합니다.
후자의 경우 TxID로 트랜잭션을 연 다음 해당 ID를 사용하여 다시 연결합니다.DBMS는 잠금을 유지하며 TxID를 통해 세션을 다시 선택할 수 있습니다.이는 2단계 커밋 프로토콜(예: XA 또는 COM+ 트랜잭션)을 사용하는 분산 트랜잭션의 작동 방식입니다.
충돌을 처리할 때 두 가지 옵션이 있습니다.
- 충돌을 피하려고 노력할 수 있습니다. 비관적 잠금이 바로 그것입니다.
- 또는 충돌이 발생하도록 허용할 수도 있지만 트랜잭션을 커밋할 때 충돌을 감지해야 하며, 이는 Optimistic Locking이 수행합니다.
이제 다음과 같은 업데이트 손실 문제를 생각해 보겠습니다.
업데이트 손실 이상은 Read Committed 분리 수준에서 발생할 수 있습니다.
위의 도표에서 우리는 앨리스가 그녀로부터 40을 인출할 수 있다고 믿는 것을 볼 수 있습니다.account
하지만 Bob이 방금 계좌 잔고를 바꿨다는 것을 깨닫지 못했고, 이제 이 계좌에는 20개밖에 남지 않았습니다.
비관적 잠금
비관적 잠금은 Bob이 계정을 변경하지 못하도록 계정에 공유 잠금 또는 읽기 잠금을 취함으로써 이 목표를 달성합니다.
위의 도표에서, Alice와 Bob 둘 다 읽기 잠금을 획득할 것입니다.account
두 사용자가 모두 읽은 테이블 행입니다.데이터베이스는 Repeatable Read 또는 Serializable을 사용할 때 SQL Server에서 이러한 잠금을 획득합니다.
왜냐하면 앨리스와 밥 둘다 책을 읽었기 때문입니다.account
이 PK인 1
, 한 사용자가 읽기 잠금을 해제할 때까지 둘 다 변경할 수 없습니다.쓰기 작업을 수행하려면 쓰기/전용 잠금 획득이 필요하고, 공유/읽기 잠금은 쓰기/전용 잠금을 방지하기 때문입니다.
앨리스가 그녀의 거래를 저지르고 읽기 잠금이 해제된 후에야.account
밥줄,UPDATE
를 재개하고 변경 사항을 적용합니다.Alice가 읽기 잠금을 해제할 때까지 Bob의 UPDATE는 차단됩니다.
낙관적 잠금
Optimistic Locking은 충돌을 허용하지만 버전이 변경된 경우 Alice's UPDATE를 적용할 때 충돌을 감지합니다.
이번에 저희가 추가로.version
칼럼. 더version
열은 UPDATE 또는 DELETE가 실행될 때마다 증가하며, UPDATE 및 DELETE 문의 WHERE 절에서도 사용됩니다.이를 위해서는 SELECT를 발행하고 전류를 읽어야 합니다.version
UPDATE 또는 DELETE를 실행하기 전에 WHERE 절에 전달하거나 증분할 버전 값을 알 수 없습니다.
애플리케이션 레벨 트랜잭션
관계형 데이터베이스 시스템은 일반적으로 클라이언트가 단말기를 통해 메인프레임에 연결하는 70년대 후반에 등장했습니다.그렇기 때문에 데이터베이스 시스템이 SESSION setting과 같은 용어를 정의하는 것을 볼 수 있습니다.
오늘날 인터넷을 통해 우리는 동일한 데이터베이스 트랜잭션의 맥락에서 읽기 및 쓰기를 더 이상 실행하지 않으며 ACID는 더 이상 충분하지 않습니다.
예를 들어 다음과 같은 사용 사례를 생각해 보십시오.
낙관적인 잠금이 없었다면 데이터베이스 트랜잭션이 Serializable을 사용했더라도 이 Lost Update를 잡을 수 없었습니다.이는 읽기와 쓰기가 별도의 HTTP 요청에서 실행되므로 서로 다른 데이터베이스 트랜잭션에서 실행되기 때문입니다.
따라서 사용자가 생각하는 시간이 포함된 애플리케이션 수준 트랜잭션을 사용하는 경우에도 낙관적인 잠금 기능을 통해 업데이트 손실을 방지할 수 있습니다.
결론
낙관적 잠금은 매우 유용한 기술이며 Read Committed와 같이 덜 엄격한 격리 수준을 사용하거나 이후 데이터베이스 트랜잭션에서 읽기 및 쓰기가 실행될 때도 잘 작동합니다.
낙관적 잠금의 단점은 데이터 액세스 프레임워크에서 롤백이 발생한다는 것입니다.OptimisticLockException
, 따라서 현재 실행 중인 트랜잭션으로 인해 이전에 수행한 모든 작업을 잃게 됩니다.
경합이 심할수록 충돌이 심해지고 거래가 중단될 가능성도 커집니다.데이터베이스 시스템에서는 테이블 행과 인덱스 레코드를 모두 포함할 수 있는 현재 보류 중인 모든 변경 사항을 되돌려야 하므로 롤백 비용이 많이 들 수 있습니다.
이러한 이유로, 비관적 잠금은 충돌이 자주 발생할 때 더 적합할 수 있는데, 이는 거래를 롤백할 가능성을 줄여주기 때문입니다.
낙관적 잠금은 많은 충돌이 예상되지 않을 때 사용됩니다.정상적인 작업을 수행하는 데는 비용이 적게 들지만 충돌이 발생하면 트랜잭션이 중단됨에 따라 이를 해결하기 위해 더 높은 비용을 지불해야 합니다.
비관적 잠금은 충돌이 예상될 때 사용됩니다.동기화를 위반할 수 있는 트랜잭션은 단순히 차단됩니다.
적절한 잠금 메커니즘을 선택하려면 읽기 및 쓰기의 양을 추정하고 그에 따라 계획해야 합니다.
낙관주의자는 당신이 그것을 읽는 동안 아무것도 변하지 않을 것이라고 가정합니다.
비관주의자는 무언가가 그렇게 될 것이라고 가정하고, 그래서 그것을 잠급니다.
데이터를 완벽하게 읽을 필요가 없는 경우에는 낙관적인 방법을 사용합니다.이상한 '더티'를 읽을 수도 있지만, 교착 상태 등이 발생할 가능성은 훨씬 낮습니다.
대부분의 웹 응용 프로그램은 더러운 읽기에도 문제가 없습니다. 드물게 데이터가 다음 재로드에 정확하게 집계되지 않는 경우도 있습니다.
많은 금융 거래에서와 같이 정확한 데이터 작업을 위해 비관적인 방법을 사용합니다.데이터를 정확하게 읽는 것이 필수적이며 표시되지 않은 변경 사항이 없습니다. 추가 잠금 오버헤드는 가치가 있습니다.
아, 그리고 Microsoft SQL Server는 기본적으로 페이지 잠금을 설정합니다. - 기본적으로 읽고 있는 행과 몇 개의 양 쪽 중 하나입니다.행 잠금이 더 정확하지만 훨씬 느립니다.읽기 중에 교착 상태가 발생하지 않도록 트랜잭션을 읽기 커밋 또는 잠금 없음으로 설정할 필요가 있는 경우가 많습니다.
비관적인 잠금이 더 나은 선택일 때 한 가지 경우를 더 생각해 보겠습니다.
낙관적 잠금을 위해서는 데이터 수정에 참여하는 모든 사람이 이러한 잠금을 사용하는 것에 동의해야 합니다.그러나 만약 누군가가 버전 열에 신경 쓰지 않고 데이터를 수정한다면, 이것은 낙관적인 잠금에 대한 전체 생각을 망칠 것입니다.
기본적으로 가장 인기있는 두가지 답이 있습니다.첫번째는 기본적으로 다음과 같이 말합니다.
Optimistic은 세션을 위해 데이터베이스에 대한 연결을 유지할 필요가 없는 3계층 아키텍처가 필요합니다. 반면, Vptiistic Locking은 레코드를 완료할 때까지 독점적으로 사용하기 위해 레코드를 잠글 때입니다.데이터베이스에 직접 연결해야 하는 낙관적 잠금보다 훨씬 우수한 무결성을 제공합니다.
낙관적(버전)은 잠금이 없기 때문에 더 빠르지만 경쟁이 심할 때는 (pessim적) 잠금이 더 잘 수행되며 작업을 폐기하고 다시 시작하는 것보다 방지하는 것이 좋습니다.
아니면
드문 충돌이 있을 때 최적의 잠금 기능
저는 "연결 유지"가 "낮은 충돌"과 어떤 관련이 있는지 설명하기 위해 답변을 작성했습니다.
어떤 전략이 자신에게 가장 적합한지 이해하려면 DB가 가지고 있는 초당 트랜잭션 수가 아니라 단일 트랜잭션의 기간을 생각해 보십시오.일반적으로 트랜잭션을 열고 작업을 수행한 후 트랜잭션을 닫습니다.이것은 ANSI가 염두에 둔 짧은 고전적인 거래이며 잠금 상태에서 벗어날 수 있습니다.그런데 많은 고객이 동시에 같은 객실/좌석을 예약하는 티켓 예매 시스템을 어떻게 구현합니까?
상품을 검색하고, 이용 가능한 다양한 옵션과 현재 가격으로 양식을 작성합니다.시간이 많이 걸리고 옵션이 쓸모없게 될 수 있습니다. 액세스한 데이터에 잠금이 없으므로 양식을 채우고 "동의합니다" 버튼을 누르기 시작했습니다. 더 민첩한 다른 사람이 모든 가격을 변경하는 데 방해가 되었기 때문입니다. 새로운 가격으로 다시 시작해야 합니다.
대신 모든 옵션을 읽을 때 잠글 수 있습니다.이것은 비관적인 시나리오입니다.왜 나쁜지 알겠네요.당신의 시스템은 단순히 예약을 시작하고 담배를 피우는 광대 한 명에 의해 다운될 수 있습니다.그가 끝나기 전에는 아무도 아무것도 예약할 수 없습니다.현금 흐름이 0으로 떨어집니다.그렇기 때문에 현실적으로 낙관적인 유보가 사용됩니다.너무 오래 어슬렁거리는 사람들은 더 비싼 가격에 예약을 다시 시작해야 합니다.
이렇게 낙관적인 접근 방식을 사용하려면 읽은 모든 데이터를 기록하고(내 반복 읽기에서와 같이) 데이터 버전을 사용하여 커밋 포인트(현재 가격이 아닌 이 견적에 표시된 가격으로 주식을 사고 싶습니다)에 도달해야 합니다.이때 ANSI 트랜잭션이 생성되며, 이 트랜잭션은 DB를 잠그고 아무것도 변경되지 않았는지 확인하며 작업을 커밋/중단합니다.IMO, 이것은 MVCC의 효과적인 에뮬레이션이며, 이것은 또한 Optimistic CC와 연관되어 있으며, 또한 당신의 트랜잭션이 중단될 경우 다시 시작되는 것을 가정합니다. 즉, 당신은 새로운 예약을 할 것입니다.여기서의 거래는 인간의 사용자 결정을 포함합니다.
MVCC를 수동으로 구현하는 방법을 이해하는 것과는 거리가 멀지만, 재시작 옵션이 있는 장기적인 거래가 주제를 이해하는 열쇠라고 생각합니다.제가 틀린 곳이 있으면 고쳐주세요.제 대답은 이 Alex Kuznecov 챕터에서 영감을 얻었습니다.
대부분의 경우 낙관적 잠금이 더 효율적이고 더 높은 성능을 제공합니다.비관적 잠금과 낙관적 잠금 중 하나를 선택할 때는 다음을 고려해야 합니다.
비관적 잠금은 업데이트가 많고 사용자가 동시에 데이터를 업데이트하려고 할 가능성이 상대적으로 높은 경우에 유용합니다.예를 들어, 각 작업이 한 번에 많은 수의 레코드를 업데이트할 수 있고(은행은 매월 말에 모든 계정에 이자 수익을 추가할 수 있음), 두 개의 애플리케이션이 동시에 이러한 작업을 실행하고 있다면 충돌이 발생할 것입니다.
비관적 잠금은 자주 업데이트되는 작은 테이블이 포함된 응용 프로그램에서도 더 적합합니다.이러한 소위 핫스팟의 경우, 충돌이 발생할 가능성이 매우 높아 낙관적인 잠금으로 인해 충돌하는 트랜잭션을 되돌리는 노력이 낭비됩니다.
낙관적 잠금은 충돌 가능성이 매우 낮은 경우에 유용합니다. 기록은 많지만 사용자는 상대적으로 적거나 업데이트가 거의 없고 대부분 읽기 유형 작업입니다.
최적 잠금의 한 가지 활용 사례는 응용 프로그램이 데이터베이스를 사용하여 스레드/호스트 중 하나가 작업을 '청구'할 수 있도록 하는 것입니다.이것은 나에게 있어 정기적으로 도움이 되는 기술입니다.
제가 생각할 수 있는 가장 좋은 예는 여러 스레드가 동시에 작업을 요청하는 데이터베이스를 사용하여 구현된 작업 대기열입니다.작업에 상태가 '사용 가능', '청구됨', '완료됨'인 경우 DB 쿼리는 "상태 설정='청구됨', 상태="와 같은 내용을 나타낼 수 있습니다.사용 가능'.여러 스레드가 이런 방식으로 상태를 변경하려고 하면 첫 번째 스레드를 제외한 모든 스레드가 더티 데이터로 인해 실패합니다.
이것은 낙관적 잠금만을 포함하는 사용 사례입니다.따라서 "많은 충돌이 예상되지 않을 때는 낙관적 잠금을 사용합니다."라고 말하는 대신 충돌이 예상되지만 하나의 트랜잭션만 성공하기를 원하는 경우에도 사용할 수 있습니다.
전자상거래 앱에서 사용자가 주문을 하려고 한다고 가정해 보겠습니다.이 코드는 여러 스레드에 의해 실행됩니다.pessimistic locking
, DB에서 데이터를 받으면 다른 스레드에서 수정할 수 없도록 잠금 처리합니다.우리는 데이터를 처리하고, 데이터를 업데이트하고, 데이터를 커밋합니다.그 다음엔 자물쇠를 풀어줍니다.여기서는 잠금 기간이 길어 데이터베이스 레코드를 처음부터 커밋할 때까지 잠갔습니다.
optimistic locking
, 데이터를 얻고 잠금 없이 데이터를 처리합니다.따라서 여러 스레드에서 지금까지의 코드를 동시에 실행할 수 있습니다.속도가 빨라질 겁니다.업데이트하는 동안 데이터를 잠급니다.우리는 그 기록을 업데이트한 다른 스레드가 없는지 확인해야 합니다.예를 들어, 만약 우리가 100개의 재고를 가지고 있고 99개로 업데이트를 해야 한다면(왜냐하면 당신의 코드는quantity=queantity-1
) 그러나 다른 스레드가 이미 1을 사용했다면 98이 되어야 합니다.가 요.race condition
여기요. 이 경우에는 스레드를 재시작하여 처음부터 동일한 코드를 실행합니다.하지만 이것은 비용이 많이 드는 작업입니다. 당신은 이미 종료했지만 다시 시작했습니다. 우리에게 몇 가지 경주 조건이 있다면 그것은 큰 문제가 되지 않을 것이고, 경주 조건이 높다면 다시 시작해야 할 스레드가 많을 것입니다.우리는 순환으로 달릴지도 모릅니다.레이스 상태가 높으면 '비관적 잠금장치'를 사용해야 합니다.
낙관적이고 비관적인 폐쇄에 대해 위에서 많은 좋은 말들이 나왔습니다.한 가지 중요한 고려 사항은 다음과 같습니다.
낙관적 잠금 기능을 사용할 때는 애플리케이션이 이러한 장애에서 어떻게 복구되는지 주의해야 합니다.
특히 비동기식 메시지 기반 아키텍처에서는 메시지 처리가 잘못되거나 업데이트가 손실될 수 있습니다.
실패 시나리오는 충분히 생각해 볼 필요가.
낙관적 잠금은 행을 읽을 때 전용 잠금이 사용되지 않으므로 업데이트 또는 쓰기 스큐가 손실되지 않습니다.따라서 낙관적 잠금을 사용합니다.
- 업데이트 또는 쓰기 스큐가 발생하지 않는 경우.
- 혹은 업데이트 손실이나 쓰기 스큐가 발생해도 문제가 없는 경우.
비관적 잠금은 행을 읽을 때 전용 잠금을 사용하므로 업데이트 또는 쓰기 스큐가 손실되지 않도록 합니다.따라서 비관적 잠금을 사용합니다.
- 업데이트 또는 쓰기 스큐가 발생하는 경우.
- 또는 업데이트 손실이나 쓰기 스큐가 발생할 경우 문제가 발생할 수 있습니다.
MySQL 및 Postgre에서SQL, 에서 전용 잠금을 사용할 수 있습니다.
당신은 MySQL 내에서 (가 없는) 낙관적인 잠금과 비관적인 잠금으로 잃어버린 업데이트에 대한 나의 답변을 확인하고 스큐 예제를 작성할 수 있습니다.
좀 더 실용적인 참고로, 분산 시스템을 업데이트할 때 DB의 최적 잠금 기능은 분산 시스템의 모든 부분에 걸쳐 필요한 일관성을 제공하기에 불충분할 수 있습니다.
예를 들어, AWS 기반으로 구축된 애플리케이션에서는 DB(예: DynamoDB)와 스토리지(예: S3) 모두에 데이터가 있는 것이 일반적입니다.업데이트가 DynamoDB와 S3 둘 다에 도달하는 경우, DynamoDB의 낙관적인 잠금은 여전히 S3의 데이터를 일관성 없이 유지할 수 있습니다.이런 경우 S3 업데이트가 완료될 때까지 DynamoDB에 유지되는 비관적 잠금을 사용하는 것이 더 안전할 수 있습니다.실제로 AWS는 이를 위해 잠금 라이브러리를 제공합니다.
낙관적 잠금 및 비관적 잠금은 데이터베이스에서 데이터를 잠그는 두 가지 모델입니다.
최적 잠금 : 데이터베이스에 변경 사항이 커밋된 경우에만 레코드가 잠기는 경우.
비관적 잠금 : 레코드가 편집되는 동안 잠기는 경우.
참고: 두 데이터 잠금 모델 모두 변경 사항이 데이터베이스에 커밋된 후 잠금이 해제됩니다.
언급URL : https://stackoverflow.com/questions/129329/optimistic-vs-pessimistic-locking
'source' 카테고리의 다른 글
그 끝에 cross(x) 버튼이 있는 EditText를 만드는 방법? (0) | 2023.10.21 |
---|---|
BLOB를 CLOB로 변환하는 방법은? (0) | 2023.10.21 |
mysql로 가져올 때 utf8 가글링됨 (0) | 2023.10.21 |
창 닫기 또는 페이지 새로 고침에서 자바스크립트 코드를 실행하시겠습니까? (0) | 2023.10.21 |
SquirreL Simplicit vjdbc VirtualDriver java.sql.SQL 예외: java.lang.Null 포인터예외. (0) | 2023.10.21 |