0Pricing
SQL Interview Prep · บทเรียน

ภาวะติดตาย การล็อก และ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. อธิบายคุณสมบัติ ACID
  2. ระดับการแยกออกจากกันทั้งสี่ระดับ
  3. การอ่านข้อมูลสกปรก การอ่านซ้ำไม่ได้ และการอ่านข้อมูลแฝง
  4. ภาวะติดตาย การล็อก และ MVCC
← กลับไปที่ SQL Interview Prep