การล็อกตารางจะป้องกันไม่ให้ผู้ใช้ 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
ขณะนี้ระบบนี้ไม่มีการล็อกและไม่มีธุรกรรมใด ๆ ระบบนี้มีความเสี่ยงต่อสภาวะการแข่งขันที่หลากหลายซึ่งใหญ่ที่สุดคือการชำระเงินหลายรายการในบัญชีของคุณหรือบัญชีของผู้รับพร้อมกัน ในขณะที่รหัสของคุณได้รับยอดเงินของคุณถูกเรียกคืนและกำลังทำขนาดใหญ่ _overdraft_fees () แต่ก็เป็นไปได้ทั้งหมดที่การชำระเงินอื่น ๆ บางส่วนจะใช้รหัสประเภทเดียวกันควบคู่กันไป พวกเขาจะเรียกคืนยอดคงเหลือของคุณ (เช่น $ 100) ทำธุรกรรมของพวกเขา (นำเงิน 20 ดอลลาร์ที่คุณจ่ายไปและ 30 ดอลลาร์ที่พวกเขากำลังทำให้คุณเสียหาย) และตอนนี้เส้นทางรหัสทั้งสองมียอดคงเหลือสองแบบ: $ 80 และ 70 เหรียญ ขึ้นอยู่กับว่ารายการใดเสร็จสิ้นสุดท้ายคุณจะได้รับยอดคงเหลือสองรายการในบัญชีของคุณแทนที่จะเป็น $ 50 ที่คุณควรได้รับ ($ 100 - $ 20 - $ 30) ในกรณีนี้ "ข้อผิดพลาดของธนาคารที่คุณโปรดปราน"
ตอนนี้สมมติว่าคุณใช้ล็อค การจ่ายบิล ($ 20) ของคุณเข้าสู่ท่อก่อนดังนั้นจึงชนะและล็อกบันทึกบัญชีของคุณ ตอนนี้คุณมีการใช้งานพิเศษและสามารถหักเงิน 20 ดอลลาร์จากยอดคงเหลือและเขียนยอดเงินใหม่กลับมาอย่างสงบ ... และบัญชีของคุณจะจบลงด้วย $ 80 ตามที่คาดไว้ แต่ ... เอ่อ ... คุณลองไปอัปเดตบัญชีของผู้รับแล้วมันถูกล็อคและล็อคนานเกินกว่าที่รหัสจะอนุญาตทำให้หมดเวลาการทำธุรกรรมของคุณ ... เรากำลังติดต่อกับธนาคารโง่ ๆ ดังนั้นแทนที่จะมีข้อผิดพลาดที่เหมาะสม การจัดการรหัสเพียงแค่ดึงexit()
และ $ 20 ของคุณหายไปในพัฟของอิเล็กตรอน ตอนนี้คุณออกเงิน 20 เหรียญและคุณยังคงเป็นหนี้ผู้รับ 20 เหรียญและโทรศัพท์ของคุณก็ถูกยึดคืน
ดังนั้น ... เข้าสู่การทำธุรกรรม คุณเริ่มต้นธุรกรรมคุณหักบัญชีของคุณ $ 20 คุณพยายามให้เครดิตผู้รับด้วย $ 20 ... และมีบางอย่างเกิดขึ้นอีกครั้ง แต่คราวนี้แทนที่จะexit()
เป็นโค้ดก็ทำได้rollback
และเงิน $ 20 ของคุณจะถูกเพิ่มกลับเข้าไปในบัญชีของคุณอย่างน่าอัศจรรย์
ในท้ายที่สุดมันก็เดือดลงถึงสิ่งนี้:
การล็อกป้องกันไม่ให้บุคคลอื่นเข้าไปยุ่งเกี่ยวกับบันทึกฐานข้อมูลใด ๆ ที่คุณกำลังติดต่อด้วย ธุรกรรมจะป้องกันไม่ให้ข้อผิดพลาด "ในภายหลัง" รบกวนสิ่งที่ "ก่อนหน้านี้" ที่คุณทำ ไม่มีใครสามารถรับประกันได้ว่าสิ่งต่างๆจะออกมาดีในที่สุด แต่ร่วมกันทำ
ในบทเรียนวันพรุ่งนี้: Joy of Deadlocks