테이블을 잠그면 다른 DB 사용자가 잠근 행 / 테이블에 영향을주지 않습니다. 그러나 잠금 자체는 논리가 일관된 상태로 나오는 것을 보장하지 않습니다.
은행 시스템을 생각해보십시오. 온라인으로 청구서를 지불 할 때 거래의 영향을받는 두 개 이상의 계정이 있습니다. 즉, 돈을 인출하는 계정입니다. 그리고 돈이 이체되는 수신자의 계정. 그리고 거래에 부과 된 모든 서비스 수수료를 기꺼이 입금 할 은행 계좌. (요즘 모두가 알고 있듯이) 은행이 엄청나게 어리 석다는 것을 감안할 때, 그들의 시스템이 다음과 같이 작동한다고 가정 해 봅시다.
$balance = "GET BALANCE FROM your ACCOUNT";
if ($balance < $amount_being_paid) {
charge_huge_overdraft_fees();
}
$balance = $balance - $amount_being paid;
UPDATE your ACCOUNT SET BALANCE = $balance;
$balance = "GET BALANCE FROM receiver ACCOUNT"
charge_insane_transaction_fee();
$balance = $balance + $amount_being_paid
UPDATE receiver ACCOUNT SET BALANCE = $balance
이제 잠금 및 거래가없는이 시스템은 다양한 경쟁 조건에 취약하며, 그중 가장 큰 것은 귀하의 계정 또는 수신자의 계정에서 동시에 수행되는 여러 결제입니다. 코드에서 잔액을 검색하고 huge_overdraft_fees () 및 기타 작업을 수행하는 동안 다른 지불이 동일한 유형의 코드를 병렬로 실행하는 것은 전적으로 가능합니다. 그들은 당신의 잔액 (예 : $ 100)을 회수하고, 그들의 거래를 할 것입니다. 70 달러. 마지막으로 완료되는 항목에 따라 계정에있는 두 잔고 중 하나가됩니다 ($ 100-$ 20-$ 30). 이 경우 "귀하의 은행 오류"
이제 잠금을 사용한다고 가정 해 보겠습니다. 청구서 지불 ($ 20)이 먼저 파이프에 도달하므로 계정 기록을 확보하고 잠급니다. 이제 독점 사용이 가능하며 잔액에서 20 달러를 공제하고 새 잔액을 안심하고 다시 쓸 수 있습니다. 그러면 계정이 예상대로 80 달러가됩니다. 하지만 ... 어 ... 당신은 수취인의 계좌를 업데이트하려고하는데, 그것은 잠겨 있고, 코드가 허용하는 것보다 더 오래 잠겼습니다. 당신의 거래 시간이 초과되었습니다 ... 우리는 어리석은 은행들을 다루고 있습니다. 처리, 코드는 단지을 당기고 exit()
$ 20는 전자의 퍼프로 사라집니다. 이제 당신은 20 달러를 내고 여전히 수신자에게 20 달러를 빚지고 있으며 전화기는 회수됩니다.
그래서 ... 거래를 입력하세요. 당신은 거래를 시작하고, 당신의 계좌에서 $ 20를 인출하고, 당신은 수신자에게 $ 20을 입금하려고합니다. 그리고 뭔가가 다시 터집니다. 그러나 이번에 exit()
는 코드 대신을 할 수 rollback
있으며 휙 휙, $ 20가 마법처럼 계정에 다시 추가됩니다.
결국 다음과 같이 요약됩니다.
잠금은 다른 사람이 처리중인 데이터베이스 레코드를 방해하지 못하도록합니다. 트랜잭션은 "이후"오류가 "이전"작업을 방해하지 않도록합니다. 둘 중 어느 쪽도 결국 모든 것이 정상적으로 작동한다고 보장 할 수 없습니다. 하지만 함께라면 그렇습니다.
내일 수업 : 교착 상태의 기쁨.