ภาวะติดตาย การล็อก และ MVCC
วิธีที่ฐานข้อมูลหลีกเลี่ยงความขัดแย้ง และข้อแลกเปลี่ยนระหว่างการล็อกกับภาพข้อมูล
ภาวะติดตาย การล็อก และ MVCC เป็นบทเรียน SQL Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
ฐานข้อมูลบังคับใช้การแยกธุรกรรมจริงอย่างไร
ระดับการแยกธุรกรรมคือคำมั่นสัญญา ส่วนการล็อกและ MVCC คือกลไกที่ทำให้คำมั่นสัญญานั้นเป็นจริง ผู้สัมภาษณ์ถามเรื่องเหล่านี้เพื่อดูว่าคุณเข้าใจสิ่งที่เกิดขึ้นเบื้องหลังเมื่อธุรกรรมชนกันหรือไม่
มีกลยุทธ์หลักอยู่สองแบบ:
- แบบระมัดระวัง (การล็อก): ระงับการเข้าถึงที่ขัดแย้งกันจนกว่าจะปล่อยล็อก
- แบบมองโลกในแง่ดี / MVCC: ให้ทุกฝ่ายอ่านภาพรวมที่สอดคล้องกัน และตรวจจับข้อขัดแย้งเมื่อยืนยันธุรกรรม
บทเรียนนี้ครอบคลุมการล็อก ภาวะติดตาย และ MVCC รวมถึงข้อแลกเปลี่ยนระหว่างวิธีเหล่านี้
ล็อกแบบใช้ร่วมกันกับล็อกแบบเฉพาะ
การล็อกแบบดั้งเดิมใช้โหมดหลักสองแบบ:
- ล็อกแบบใช้ร่วมกัน (S) สำหรับการอ่าน ธุรกรรมหลายรายการสามารถถือล็อกแบบใช้ร่วมกันบนแถวเดียวกันได้พร้อมกัน
- ล็อกแบบเฉพาะ (X) สำหรับการเขียน มีธุรกรรมเพียงรายการเดียวที่ถือครองได้ และล็อกนี้จะขัดขวางล็อกชนิดอื่นทั้งหมดบนแถวนั้น
กฎคือ S ใช้ร่วมกับ S ได้ แต่ X ใช้ร่วมกับอะไรไม่ได้ ธุรกรรมที่เขียนต้องรอธุรกรรมที่อ่านทั้งหมด และธุรกรรมที่อ่านต้องรอธุรกรรมที่เขียน
การล็อกอย่างชัดเจนด้วย SELECT FOR UPDATE
คุณสามารถขอล็อกสำหรับเขียนบนแถวที่คุณอ่านเพียงอย่างเดียว เพื่อป้องกันไม่ให้ผู้อื่นเปลี่ยนแถวเหล่านั้นก่อนที่คุณจะดำเนินการ วิธีนี้เป็นมาตรฐานสำหรับหลีกเลี่ยง การปรับปรุงที่สูญหาย ในกระบวนการอ่าน-แก้ไข-เขียน
SELECT ... FOR UPDATE จะใช้ล็อกแบบเฉพาะกับแถว และแถวเหล่านั้นจะยังคงถูกล็อกจนกว่าคุณจะใช้ COMMIT หรือ ROLLBACK
BEGIN;
-- lock the row so no one else can modify it concurrently
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT; -- lock released hereภาวะติดตายคืออะไร
ภาวะติดตาย เกิดขึ้นเมื่อธุรกรรมตั้งแต่สองรายการขึ้นไปต่างถือครองล็อกที่อีกฝ่ายต้องการ จนเกิดเป็นวงจรที่ไม่มีธุรกรรมใดดำเนินการต่อได้
กรณีตัวอย่างในตำราคือ T1 ล็อกแถว A แล้วต้องการแถว B ส่วน T2 ล็อกแถว B แล้วต้องการแถว A ทั้งคู่จึงรออีกฝ่ายไปตลอด
ฐานข้อมูลตรวจจับเหตุการณ์นี้ด้วย กราฟการรอคอย เมื่อพบวงจร เอ็นจินจะเลือก ธุรกรรมที่ถูกเลือกยกเลิก แล้วหยุดธุรกรรมนั้น พร้อมส่งข้อผิดพลาดภาวะติดตาย เพื่อให้ธุรกรรมอื่นดำเนินการต่อได้
ภาวะติดตาย: ลำดับเวลา
สังเกตลำดับล็อกที่ไขว้กัน T1 ล็อกแถวที่ 1 แล้วขอแถวที่ 2 ส่วน T2 ล็อกแถวที่ 2 แล้วขอแถวที่ 1 ไม่มีฝ่ายใดปล่อยล็อก ดังนั้นเอ็นจินจึงยกเลิกหนึ่งธุรกรรม
ธุรกรรมที่ถูกยกเลิกจะเห็นข้อผิดพลาดอย่าง deadlock detected และต้องลองทำซ้ำ ส่วนธุรกรรมที่เหลือรอดจะยืนยันการทำรายการตามปกติ
-- T1 | -- T2
BEGIN; | BEGIN;
UPDATE accounts SET balance=balance-10 | UPDATE accounts SET balance=balance-10
WHERE id=1; -- locks row 1 | WHERE id=2; -- locks row 2
UPDATE accounts SET balance=balance+10 | UPDATE accounts SET balance=balance+10
WHERE id=2; -- waits for T2 | WHERE id=1; -- waits for T1 -> CYCLE
-- one transaction is chosen as victim and rolled backการป้องกันภาวะติดตาย
คุณไม่สามารถกำจัดภาวะติดตายได้ทั้งหมด แต่ทำให้เกิดขึ้นได้ยากลง คำตอบมาตรฐานในการสัมภาษณ์มีดังนี้:
- ลำดับการล็อกที่สอดคล้องกัน: ล็อกแถวตามลำดับเดียวกันเสมอ เช่น เรียงตามค่าประจำตัวจากน้อยไปมาก วิธีนี้จะทำลายวงจร
- ทำธุรกรรมให้สั้น: ถือล็อกไว้เป็นเวลาน้อยที่สุดเท่าที่ทำได้
- ลดระดับการแยกธุรกรรมเมื่อปลอดภัย: ล็อกน้อยลง ข้อขัดแย้งก็น้อยลง
- เพิ่มตรรกะการลองใหม่: ธุรกรรมที่ถูกเลือกยกเลิกจากภาวะติดตายควรลองทำซ้ำโดยอัตโนมัติ
การจัดลำดับให้สอดคล้องกันเป็นวิธีแก้ที่มีประสิทธิภาพที่สุด และเป็นคำตอบแรกที่ผู้สัมภาษณ์ต้องการได้ยิน
ระดับความละเอียดของการล็อก
สามารถใช้ล็อกในขอบเขตต่าง ๆ ได้ เป็นการแลกเปลี่ยนระหว่างการทำงานพร้อมกันกับภาระระบบ:
- ล็อกระดับแถวช่วยให้ทำงานพร้อมกันได้มาก แต่มีต้นทุนในการจัดการสูงกว่า
- ล็อกระดับหน้าหรือตารางมีต้นทุนในการติดตามต่ำกว่า แต่ขัดขวางธุรกรรมได้มากกว่า
เอ็นจินบางชนิดยกระดับจากล็อกระดับแถวเป็นล็อกระดับตารางเมื่อธุรกรรมแตะต้องแถวจำนวนมากเกินไป (การยกระดับล็อก) การรู้เรื่องนี้ช่วยอธิบายว่าเหตุใดการใช้ UPDATE จำนวนมากแบบเป็นชุดจึงอาจขัดขวางทุกคนได้ทันที
MVCC: แนวทางการใช้ภาพรวม
MVCC (การควบคุมการทำงานพร้อมกันหลายเวอร์ชัน) คือวิธีที่โพสต์เกรส ออราเคิล และ InnoDB ใช้เพื่อหลีกเลี่ยงล็อกสำหรับการอ่านส่วนใหญ่ แทนที่จะใช้การล็อก ฐานข้อมูลจะเก็บ เวอร์ชันหลายชุดของแต่ละแถวไว้
ประโยชน์สำคัญและเป็นประโยคสั้นที่ผู้สัมภาษณ์ชอบถามคือ: ผู้ที่อ่านไม่ขัดขวางผู้ที่เขียน และผู้ที่เขียนไม่ขัดขวางผู้ที่อ่าน
แต่ละธุรกรรมจะเห็นภาพรวมที่สอดคล้องกัน ณ จุดเวลาหนึ่ง ขณะที่ธุรกรรมที่เขียนจะสร้างเวอร์ชันใหม่ของแถว แทนการเขียนทับข้อมูลเดิมในตำแหน่งเดิม
MVCC ทำงานเบื้องหลังอย่างไร
เมื่อมีการแก้ไขแถว MVCC จะเขียนเวอร์ชันใหม่และเก็บเวอร์ชันเก่าไว้ แต่ละเวอร์ชันมีข้อมูลเมตาของรหัสธุรกรรม (ในโพสต์เกรสคือ xmin และ xmax) ซึ่งระบุเวลาที่เวอร์ชันนั้นเริ่มมองเห็นได้และเวลาที่ถูกแทนที่
ภาพรวมของธุรกรรมจะกำหนดว่าธุรกรรมนั้นเห็นเวอร์ชันใด เวอร์ชันเก่าที่ไม่มีธุรกรรมใดมองเห็นได้อีกจะกลายเป็นทูเพิลที่หมดสภาพ และถูกเรียกคืนภายหลังโดยกระบวนการล้างข้อมูล ในโพสต์เกรส กระบวนการนั้นคือ VACUUM หากไม่เรียกใช้จะทำให้เกิดตารางพองตัว ซึ่งเป็นคำถามต่อยอดที่พบบ่อย
การล็อกกับ MVCC: ข้อแลกเปลี่ยน
สรุปการเปรียบเทียบอย่างกระชับ:
- การล็อกล้วน: รับรองความถูกต้องได้ง่าย แต่ผู้ที่อ่านและผู้ที่เขียนจะขัดขวางกันเอง ทำให้การทำงานพร้อมกันลดลง
- MVCC: รองรับการอ่านพร้อมกันได้ดีเยี่ยม ไม่ต้องใช้ล็อกสำหรับการอ่าน แต่ต้องแลกด้วยพื้นที่จัดเก็บเวอร์ชันและการล้างข้อมูล (VACUUM, ตารางพองตัว) และยังต้องใช้ล็อกสำหรับข้อขัดแย้งระหว่างการเขียน
แม้เอ็นจินที่ใช้ MVCC ก็ยังใช้ล็อกเมื่อเขียน ธุรกรรมสองรายการที่แก้ไขแถวเดียวกันต้องทำงานเรียงลำดับกัน MVCC ขจัดการแย่งทรัพยากรระหว่างการอ่านกับการเขียน แต่ไม่ได้ขจัดการแย่งทรัพยากรระหว่างการเขียนด้วยกันเอง
การล็อกแบบมองโลกในแง่ดีและคอลัมน์เวอร์ชัน
นอกเหนือจาก MVCC ระดับเอ็นจินแล้ว แอปพลิเคชันมักเพิ่มการล็อกแบบมองโลกในแง่ดีสำหรับกระบวนการอ่าน-แก้ไข-เขียนตลอดช่วงการใช้งานของผู้ใช้ที่ยาวนาน คุณเพิ่มคอลัมน์ version อ่านค่า แล้วเมื่อแก้ไขให้กำหนดว่าเวอร์ชันต้องตรงกัน พร้อมเพิ่มค่าเวอร์ชัน
หากธุรกรรมอื่นแก้ไขแถวก่อน เวอร์ชันจะไม่ตรงกัน ไม่มีแถวใดได้รับผลกระทบ และโค้ดของคุณจะทราบว่าต้องโหลดข้อมูลใหม่แล้วลองอีกครั้ง ไม่ต้องถือล็อกไว้ระหว่างที่ผู้ใช้กำลังคิด การทำงานพร้อมกันจึงยังอยู่ในระดับสูง ผู้สัมภาษณ์ชอบแนวทางนี้สำหรับคำถามว่า "คุณจัดการอย่างไรเมื่อผู้ใช้สองคนแก้ไขระเบียนเดียวกัน?"
-- read: SELECT id, data, version FROM items WHERE id = 1; -- version = 7
UPDATE items
SET data = 'new value', version = version + 1
WHERE id = 1 AND version = 7;
-- if rows affected = 0, someone else changed it: reload and retryตรวจสอบอย่างรวดเร็ว
ทดสอบประโยคสำคัญของ MVCC
สรุป: ล็อก ภาวะติดตาย และ MVCC
ขณะนี้คุณสามารถอธิบายกลไกเบื้องหลังการแยกธุรกรรมได้แล้ว:
- ล็อกแบบใช้ร่วมกัน/แบบเฉพาะประสานการเข้าถึงข้อมูล ส่วน
SELECT FOR UPDATEใช้ล็อกสำหรับเขียนอย่างชัดเจน - ภาวะติดตายคือวงจรของล็อก เอ็นจินจะยกเลิกธุรกรรมหนึ่งที่ถูกเลือก และการจัดลำดับล็อกอย่างสอดคล้องกันจะป้องกันภาวะติดตายส่วนใหญ่ได้
- MVCCเก็บเวอร์ชันของแถวไว้ ทำให้ผู้ที่อ่านและผู้ที่เขียนไม่ขัดขวางกัน โดยแลกกับภาระการล้างข้อมูล (VACUUM, ตารางพองตัว)
เมื่อจับคู่กลไกเหล่านี้กับระดับการแยกธุรกรรมและความผิดปกติจากบทเรียนก่อนหน้า คุณก็สามารถตอบคำถามสัมภาษณ์เรื่องการทำงานพร้อมกันได้ครบตั้งแต่ต้นจนจบ
คำถามที่พบบ่อย
บทเรียน “ภาวะติดตาย การล็อก และ MVCC” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ภาวะติดตาย การล็อก และ MVCC” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ภาวะติดตาย การล็อก และ MVCC”
วิธีที่ฐานข้อมูลหลีกเลี่ยงความขัดแย้ง และข้อแลกเปลี่ยนระหว่างการล็อกกับภาพข้อมูล คุณปฏิบัติ SQL Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Interview Prep หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “ภาวะติดตาย การล็อก และ MVCC” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน SQL Interview Prep นี้ได้ไหม
ได้ บทเรียน SQL Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- อธิบายคุณสมบัติ ACID
- ระดับการแยกออกจากกันทั้งสี่ระดับ
- การอ่านข้อมูลสกปรก การอ่านซ้ำไม่ได้ และการอ่านข้อมูลแฝง
- ภาวะติดตาย การล็อก และ MVCC