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

ระดับการแยกออกจากกันทั้งสี่ระดับ

ตั้งแต่ Read Uncommitted ถึง Serializable และทำความเข้าใจว่าแต่ละระดับอนุญาตให้เกิดอะไรได้บ้าง

ระดับการแยกออกจากกันทั้งสี่ระดับ เป็นบทเรียน Coding Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Coding Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คำถามที่ซ่อนอยู่เบื้องหลัง

เมื่อผู้สัมภาษณ์ถามว่า "จงบอกระดับการแยกธุรกรรมทั้งสี่" สิ่งที่ต้องการทดสอบจริง ๆ คือคุณอธิบายการแลกเปลี่ยนได้หรือไม่: การแยกธุรกรรมที่เข้มงวดขึ้นหมายถึงความผิดปกติน้อยลง แต่ความสามารถในการทำงานพร้อมกันลดลง

มาตรฐานเอสคิวแอลกำหนดไว้สี่ระดับ โดยเรียงจากอ่อนที่สุดไปเข้มงวดที่สุด:

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE

แต่ละระดับอนุญาตหรือห้ามความผิดปกติจากการอ่านชุดหนึ่งโดยเฉพาะ บทเรียนนี้ครอบคลุมระดับต่าง ๆ ส่วนบทถัดไปจะอธิบายความผิดปกติเหล่านั้นอย่างละเอียด

การกำหนดระดับการแยกธุรกรรม

คุณกำหนดการแยกธุรกรรมแยกเป็นรายธุรกรรมหรือรายเซสชันได้ รูปแบบคำสั่งเกือบเหมือนกันในระบบประมวลผลต่าง ๆ

หากคุณไม่กำหนด ฐานข้อมูลแต่ละระบบจะมีค่าเริ่มต้น การรู้ค่าดังกล่าวเป็นคำถามที่พบบ่อยในการสัมภาษณ์ เราจึงจะอธิบายเรื่องนี้ในตอนท้าย

-- Per transaction (standard SQL)
BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- ... statements ...
COMMIT;

-- Per session
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

ระดับที่ 1: READ UNCOMMITTED

READ UNCOMMITTED เป็นระดับที่อ่อนที่สุด ธุรกรรมหนึ่งสามารถอ่านแถวข้อมูลที่อีกธุรกรรมหนึ่งแก้ไขแล้วแต่ยังไม่ได้ยืนยันผลได้ การอ่านเช่นนี้เรียกว่าการอ่านข้อมูลที่ยังไม่ยืนยัน

หากธุรกรรมอีกรายการนั้นย้อนกลับ คุณก็ได้อ่านข้อมูลที่ไม่เคยมีอยู่จริงอย่างเป็นทางการ ซึ่งเป็นอันตรายต่อทุกสิ่งที่ต้องการความถูกต้อง

หมายเหตุ: โพสต์เกรสปฏิบัติต่อ READ UNCOMMITTED เหมือนกับ READ COMMITTED จึงไม่เกิดการอ่านข้อมูลที่ยังไม่ยืนยันจริง เซิร์ฟเวอร์เอสคิวแอลและ MySQL รองรับระดับนี้ตามที่กำหนด

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN;
-- may see another transaction's uncommitted (dirty) rows
SELECT balance FROM accounts WHERE id = 1;
COMMIT;

ระดับที่ 2: READ COMMITTED

READ COMMITTED รับรองว่าคุณจะอ่านได้เฉพาะข้อมูลที่ยืนยันผลแล้วเท่านั้น จึงไม่มีการอ่านข้อมูลที่ยังไม่ยืนยัน

อย่างไรก็ตาม แต่ละคำสั่งจะเห็นภาพรวมล่าสุดของข้อมูลที่ยืนยันผลแล้ว หากคุณเรียกใช้คำสั่งค้นหาเดิมสองครั้งในธุรกรรมเดียว ธุรกรรมอื่นที่ยืนยันผลแล้วระหว่างการเรียกใช้ทั้งสองครั้งอาจเปลี่ยนผลลัพธ์ได้ ความผิดปกตินี้เรียกว่าการอ่านซ้ำแล้วได้ค่าไม่เหมือนเดิม

นี่คือค่าเริ่มต้นในโพสต์เกรส ออราเคิล และเซิร์ฟเวอร์เอสคิวแอล และเป็นสมดุลที่เหมาะสมสำหรับแอปพลิเคชันส่วนใหญ่

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
SELECT balance FROM accounts WHERE id = 1;  -- returns 500
-- another transaction commits an update to id = 1
SELECT balance FROM accounts WHERE id = 1;  -- may now return 700
COMMIT;

ระดับที่ 3: REPEATABLE READ

REPEATABLE READ รับรองว่าหากคุณอ่านแถวข้อมูลเดิมสองครั้งในธุรกรรมเดียวกัน คุณจะได้ค่าเดิมทั้งสองครั้ง ระดับนี้จะสร้างภาพรวมข้อมูลที่สอดคล้องกันเมื่อเริ่มธุรกรรม

ระดับนี้ป้องกันการอ่านข้อมูลที่ยังไม่ยืนยันและการอ่านซ้ำแล้วได้ค่าไม่เหมือนเดิม แต่มาตรฐานยังอนุญาตให้เกิดการอ่านพบแถวใหม่ได้ นั่นคือแถวใหม่ที่ตรงกับเงื่อนไข WHERE ของคุณปรากฏขึ้นเมื่อค้นหาซ้ำ

สำคัญ: นี่คือค่าเริ่มต้นใน MySQL/InnoDB และการทำงานของ InnoDB ยังป้องกันแถวใหม่ส่วนใหญ่ได้ด้วยการล็อกแบบคีย์ถัดไป

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
SELECT balance FROM accounts WHERE id = 1;  -- 500
-- another transaction commits a change to id = 1
SELECT balance FROM accounts WHERE id = 1;  -- still 500 in this txn
COMMIT;

ระดับที่ 4: SERIALIZABLE

SERIALIZABLE เป็นระดับที่เข้มงวดที่สุด ฐานข้อมูลรับรองว่าผลลัพธ์ของธุรกรรมที่ทำงานพร้อมกันจะเหมือนกับการเรียกใช้ธุรกรรมทีละรายการตามลำดับใดลำดับหนึ่ง

ระดับนี้ป้องกันการอ่านข้อมูลที่ยังไม่ยืนยัน การอ่านซ้ำแล้วได้ค่าไม่เหมือนเดิม และการอ่านพบแถวใหม่ ต้นทุนคือการล็อกที่มากขึ้น หรือในโพสต์เกรสอาจเกิดการยกเลิกเนื่องจากการจัดลำดับล้มเหลว ซึ่งคุณต้องเรียกใช้ธุรกรรมใหม่

ถ้อยคำสำหรับการสัมภาษณ์: "SERIALIZABLE ทำให้ดูเสมือนว่าธุรกรรมทุกรายการทำงานเพียงลำพัง โดยแลกกับความสามารถในการทำงานพร้อมกันที่ลดลงและความเป็นไปได้ที่จะต้องลองใหม่"

BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT SUM(balance) FROM accounts;
INSERT INTO audit (total) VALUES (...);
COMMIT;  -- may raise a serialization_failure you retry

ตารางความผิดปกติ

สิ่งที่มีประโยชน์ที่สุดและควรจดจำคือแต่ละระดับอนุญาตให้เกิดความผิดปกติใดบ้าง คำว่า "ใช่" หมายความว่าความผิดปกตินั้นอาจเกิดขึ้นได้

  • READ UNCOMMITTED: การอ่านข้อมูลที่ยังไม่ยืนยัน=ใช่ การอ่านซ้ำแล้วได้ค่าไม่เหมือนเดิม=ใช่ การอ่านพบแถวใหม่=ใช่
  • READ COMMITTED: การอ่านข้อมูลที่ยังไม่ยืนยัน=ไม่ใช่ การอ่านซ้ำแล้วได้ค่าไม่เหมือนเดิม=ใช่ การอ่านพบแถวใหม่=ใช่
  • REPEATABLE READ: การอ่านข้อมูลที่ยังไม่ยืนยัน=ไม่ใช่ การอ่านซ้ำแล้วได้ค่าไม่เหมือนเดิม=ไม่ใช่ การอ่านพบแถวใหม่=ใช่ (ตามมาตรฐาน)
  • SERIALIZABLE: การอ่านข้อมูลที่ยังไม่ยืนยัน=ไม่ใช่ การอ่านซ้ำแล้วได้ค่าไม่เหมือนเดิม=ไม่ใช่ การอ่านพบแถวใหม่=ไม่ใช่

ทุกขั้นที่เลื่อนขึ้นจะห้ามความผิดปกติเพิ่มขึ้นอีกหนึ่งแบบ ความก้าวหน้าตามลำดับนี้คือคำตอบทั้งหมด

มาตรฐานกับการทำงานจริงของระบบ

ข้อแตกต่างในระดับผู้มีประสบการณ์คือ มาตรฐานเอสคิวแอลกำหนดระดับต่าง ๆ ตามความผิดปกติที่แต่ละระดับต้องป้องกัน ไม่ได้กำหนดวิธีการป้องกัน ระบบประมวลผลจริงมักป้องกันได้มากกว่านั้น

  • โพสต์เกรส REPEATABLE READ ใช้การแยกธุรกรรมด้วยภาพรวมและป้องกันการอ่านพบแถวใหม่ด้วย แต่ยังอาจพบความขัดแย้งจากการเขียนแบบเหลื่อมกัน
  • MySQL/InnoDB REPEATABLE READ ป้องกันการอ่านพบแถวใหม่ด้วยการล็อกแบบคีย์ถัดไป
  • โพสต์เกรส SERIALIZABLE ใช้ SSI (การแยกธุรกรรมด้วยภาพรวมแบบจัดลำดับได้) และยกเลิกธุรกรรมเมื่อเกิดความขัดแย้งแทนการใช้การล็อกจำนวนมาก

การกล่าวถึงเรื่องนี้แสดงให้เห็นว่าคุณรู้ว่ามาตรฐานเป็นเพียงขอบเขตขั้นต่ำ ไม่ใช่พฤติกรรมที่เกิดขึ้นจริงทั้งหมด

ระดับเริ่มต้นของแต่ละระบบประมวลผล

เรื่องค่าเริ่มต้นมักถูกถามอยู่เสมอ โปรดจำข้อมูลเหล่านี้ให้ขึ้นใจ:

  • PostgreSQL: READ COMMITTED
  • ออราเคิล: READ COMMITTED (ไม่มีการอ่านข้อมูลที่ยังไม่ยืนยันเลย)
  • เซิร์ฟเวอร์เอสคิวแอล: READ COMMITTED
  • MySQL (InnoDB): REPEATABLE READ

ข้อแตกต่างของ MySQL เป็นจุดหลอกที่ผู้สัมภาษณ์ชอบถาม หากถูกถามว่า "ระดับการแยกธุรกรรมเริ่มต้นคืออะไร" ให้ตรวจสอบก่อนเสมอว่าหมายถึงระบบประมวลผลใด

การเลือกระดับในทางปฏิบัติ

คุณจะตัดสินใจอย่างไร ให้พิจารณาเรื่องความเสี่ยงเทียบกับปริมาณงานที่ระบบรองรับ

  • ใช้ READ COMMITTED สำหรับงาน OLTP ทั่วไป เพราะทำงานได้รวดเร็วและหลีกเลี่ยงการอ่านข้อมูลที่ยังไม่ยืนยัน
  • ใช้ REPEATABLE READ เมื่อธุรกรรมอ่านข้อมูลเดิมหลายครั้งและข้อมูลนั้นต้องคงที่ เช่น รายงานหรือการคำนวณหลายขั้นตอน
  • ใช้ SERIALIZABLE กับตรรกะที่ต้องการความถูกต้องอย่างยิ่ง ซึ่งยอมให้เกิดความผิดปกติไม่ได้ และออกแบบตรรกะสำหรับการลองใหม่เมื่อธุรกรรมถูกยกเลิก

แทบไม่ควรใช้ READ UNCOMMITTED ในระบบใช้งานจริง

คำถามต่อยอดที่พบบ่อย

เมื่อคุณบอกระดับต่าง ๆ ครบแล้ว ผู้สัมภาษณ์มักถามต่ออย่างรวดเร็ว โปรดเตรียมคำตอบที่กระชับไว้:

  • "ระดับใดป้องกันการอ่านข้อมูลที่ยังไม่ยืนยัน แต่ยังอนุญาตให้การอ่านซ้ำแล้วได้ค่าไม่เหมือนเดิมเกิดขึ้นได้" READ COMMITTED
  • "ความผิดปกติเดียวที่ REPEATABLE READ ยังคงอนุญาตตามมาตรฐานคืออะไร" การอ่านพบแถวใหม่
  • "เหตุใดจึงไม่ใช้ SERIALIZABLE เสมอไป" เพราะลดความสามารถในการทำงานพร้อมกัน และอาจบังคับให้ลองธุรกรรมใหม่เมื่อการจัดลำดับล้มเหลว
  • "ระดับที่สูงขึ้นมีต้นทุนมากขึ้นหรือไม่" มี ทั้งในรูปการล็อกหรือค่าใช้จ่ายจากการยกเลิกแล้วลองใหม่

การตอบคำถามเหล่านี้ได้ทันทีแสดงว่าคุณเข้าใจลำดับขั้นอย่างแท้จริง ไม่ใช่เพียงท่องจำ

ตรวจสอบความเข้าใจอย่างรวดเร็ว

หนึ่งในข้อต่อไปนี้คือข้อเท็จจริงเรื่องค่าเริ่มต้นที่มักถูกทดสอบมากที่สุด

สรุป: สี่ระดับกับการแลกเปลี่ยนหนึ่งประการ

ระดับการแยกธุรกรรมทั้งสี่เรียงเป็นลำดับจากอ่อนที่สุดไปเข้มงวดที่สุด ได้แก่ READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE ทุกขั้นที่เลื่อนขึ้นจะห้ามความผิดปกติเพิ่มอีกหนึ่งแบบ (การอ่านข้อมูลที่ยังไม่ยืนยัน การอ่านซ้ำแล้วได้ค่าไม่เหมือนเดิม และการอ่านพบแถวใหม่) โดยแลกกับความสามารถในการทำงานพร้อมกันที่ลดลง

จดจำค่าเริ่มต้นไว้ว่าเป็น READ COMMITTED ในทุกระบบ ยกเว้น REPEATABLE READ ของ MySQL และจำไว้ว่าระบบประมวลผลจริงมักป้องกันความผิดปกติได้มากกว่าที่มาตรฐานกำหนด ต่อไปเราจะตรวจสอบความผิดปกติจากการอ่านทั้งสามแบบที่ระดับเหล่านี้ออกแบบมาเพื่อป้องกัน

คำถามที่พบบ่อย

บทเรียน “ระดับการแยกออกจากกันทั้งสี่ระดับ” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ระดับการแยกออกจากกันทั้งสี่ระดับ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Coding Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ระดับการแยกออกจากกันทั้งสี่ระดับ”

ตั้งแต่ Read Uncommitted ถึง Serializable และทำความเข้าใจว่าแต่ละระดับอนุญาตให้เกิดอะไรได้บ้าง คุณปฏิบัติ Coding Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Coding Interview Prep หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Coding Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “ระดับการแยกออกจากกันทั้งสี่ระดับ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Coding Interview Prep นี้ได้ไหม

ได้ บทเรียน Coding Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

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

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