PlusMagi's Blog By Pitt Phunsanit Backend,Database ทำความเข้าใจ Transaction Isolation Levels: การแก้ปัญหา Dirty Read, Non-Repeatable Read, และ Phantom Read

ทำความเข้าใจ Transaction Isolation Levels: การแก้ปัญหา Dirty Read, Non-Repeatable Read, และ Phantom Read

ในโลกของการพัฒนาแอปพลิเคชันขนาดใหญ่ (Enterprise Applications) ที่ต้องรองรับการทำธุรกรรมจำนวนมหาศาลพร้อมกัน (High Concurrency) การจัดการความถูกต้องของข้อมูลจึงเป็นภารกิจที่สำคัญที่สุด เมื่อหลายกระบวนการ (Processes) พยายามเข้าถึง แก้ไข หรืออ่านชุดข้อมูลเดียวกันในเวลาเดียวกัน ปรากฏการณ์ความขัดแย้งของข้อมูล (Concurrency Issues) ย่อมเกิดขึ้นได้ ทำให้ข้อมูลที่เราเห็นอาจไม่สอดคล้องกับความเป็นจริง ณ ขณะนั้น

หัวใจสำคัญของการรับประกันความน่าเชื่อถือของข้อมูลคือแนวคิดของ Transaction Isolation Levels ซึ่งเป็นกลไกที่กำหนดว่าธุรกรรม (Transaction) หนึ่ง ๆ จะมองเห็นการเปลี่ยนแปลงของข้อมูลจากธุรกรรมอื่นในระดับใด โดยมีเป้าหมายหลักเพื่อรักษาคุณสมบัติ ACID (Atomicity, Consistency, Isolation, Durability) ให้คงอยู่

ทำความเข้าใจปัญหาความไม่สอดคล้องของข้อมูล (Data Inconsistency)

ก่อนจะเข้าใจวิธีแก้ไข เราต้องเข้าใจปัญหาที่เกิดขึ้นก่อน โดยปัญหาหลัก 3 ประการที่วิศวกรต้องระวังคือ:

  • Dirty Read: การอ่านข้อมูลที่ถูกแก้ไขโดยธุรกรรมอื่น แต่ธุรกรรมนั้นยังไม่ได้ทำการ Commit (ข้อมูลอาจถูกยกเลิกในภายหลัง)
  • Non-Repeatable Read: การรัน Query เดิมซ้ำในธุรกรรมเดียวกัน แต่กลับได้ค่าที่แตกต่างกัน เพราะธุรกรรมอื่นได้ทำการแก้ไขและ Commit ข้อมูลนั้นไปแล้ว
  • Phantom Read: การรัน Query ที่ใช้เงื่อนไข (WHERE clause) เดิมซ้ำ แต่ระบบกลับพบแถวข้อมูล (Row) ใหม่ที่ไม่เคยมีมาก่อน เพราะธุรกรรมอื่นได้แทรก (Insert) แถวข้อมูลใหม่เข้ามา

Isolation Levels ใน PostgreSQL: การป้องกันความขัดแย้ง

PostgreSQL เป็นระบบฐานข้อมูลที่แข็งแกร่งและมีการจัดการ Isolation Levels ที่ชัดเจน โดยมีระดับมาตรฐานให้เลือกใช้ ได้แก่ Read Committed, Repeatable Read, และ Serializable

ระดับมาตรฐานและกลไกการป้องกัน

โดยค่าเริ่มต้น (Default) ของ PostgreSQL คือ Read Committed ซึ่งมีประสิทธิภาพสูงและป้องกันปัญหา Dirty Read ได้อย่างสมบูรณ์ แต่หากต้องการความแม่นยำสูงสุด เราต้องปรับระดับ:

  1. Read Committed (Default): ป้องกัน Dirty Read แต่ยังเสี่ยงต่อ Non-Repeatable Read และ Phantom Read
  2. Repeatable Read: ป้องกัน Dirty Read และ Non-Repeatable Read โดยการล็อคข้อมูลที่อ่านไปแล้ว ทำให้มั่นใจได้ว่าค่าที่อ่านซ้ำจะเหมือนเดิม
  3. Serializable: เป็นระดับสูงสุด ป้องกันปัญหาทั้งสามประเภท (Dirty, Non-Repeatable, Phantom) โดยการทำให้ธุรกรรมทั้งหมดทำงานเสมือนว่ารันในสภาพแวดล้อมที่ไม่มีใครรบกวนเลย

ตัวอย่างการใช้งานใน PostgreSQL

การกำหนดระดับ Isolation Level ต้องทำภายในขอบเขตของ Transaction เสมอ เพื่อให้การทำงานเป็นไปอย่างมีขอบเขต:

SQL

-- 1. เริ่มต้น Transaction และกำหนดระดับเป็น Repeatable Read<br>BEGIN;<br>SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;<br><br>-- 2. ทำการ Query ที่ต้องการความสม่ำเสมอของข้อมูล<br>SELECT * FROM accounts WHERE user_id = 1;<br><br>-- 3. เมื่อเสร็จสิ้น ให้ Commit<br>COMMIT;<br>

การใช้ SET TRANSACTION ISOLATION LEVEL ทำให้เราสามารถควบคุมพฤติกรรมการมองเห็นข้อมูลได้อย่างแม่นยำตามความต้องการทางธุรกิจ ซึ่งเป็นหลักการที่ Senior Developer ต้องเข้าใจอย่างลึกซึ้ง

บทสรุป: การเลือกใช้ระดับที่เหมาะสม

การเลือก Isolation Level ที่ถูกต้องไม่ใช่แค่การเลือกค่าจากลิสต์ แต่คือการวิเคราะห์ความเสี่ยงของแอปพลิเคชันนั้น ๆ หากแอปพลิเคชันต้องการความรวดเร็วและยอมรับความเสี่ยงเล็กน้อย Read Committed อาจเพียงพอ แต่หากเป็นการทำธุรกรรมทางการเงินที่ต้องมั่นใจว่าข้อมูลจะไม่เปลี่ยนแปลงระหว่างการประมวลผล การใช้ Repeatable Read หรือ Serializable คือคำตอบที่ถูกต้องที่สุด การเข้าใจกลไกเหล่านี้จะช่วยให้ระบบฐานข้อมูลของคุณมีความเสถียรและเชื่อถือได้ในระดับสถาปัตยกรรม (Architectural Level)

Exit mobile version