ทำความเข้าใจ PostgreSQL Transactions คืออะไรและทำไมต้องใช้
ถ้าคุณกำลังฝึกทำระบบจัดการฐานข้อมูล (Database) ต้องเคยเจอเหตุการณ์ที่ข้อมูลต้องอัปเดตหลายที่พร้อมกัน PostgreSQL Transactions (การรวมชุดคำสั่งให้ทำงานเป็นก้อนเดียว) คือวิธีป้องกันปัญหาข้อมูลค้างคาหรือผิดพลาดระหว่างทำรายการ
ลองนึกภาพตอนคุณโอนเงินผ่านแอปธนาคาร ถ้าเงินถูกหักจากบัญชีคุณแล้ว แต่ระบบล่มก่อนโอนเข้าบัญชีปลายทาง จะเกิดอะไรขึ้น ธุรกรรมจะช่วยให้มั่นใจว่า ถ้าทำไม่สำเร็จครบทุกขั้นตอน ระบบจะยกเลิกทุกอย่างกลับไปจุดเริ่มต้นเหมือนไม่มีอะไรเกิดขึ้น
มือใหม่มักมองข้ามเรื่องนี้จนเจอปัญหาข้อมูลไม่ตรงกันในอนาคต การเข้าใจเรื่องนี้จะทำให้แอปที่คุณเขียนมีความน่าเชื่อถือและจัดการข้อมูลได้แม่นยำขึ้นมาก
ควบคุมธุรกรรมด้วย BEGIN, COMMIT และ ROLLBACK
การควบคุมธุรกรรมหลักๆ มี 3 คำสั่งที่คุณต้องรู้จักและใช้ให้คล่อง BEGIN (เริ่มธุรกรรม) คือการบอกฐานข้อมูลว่าเราจะเริ่มทำงานเป็นชุดแล้วนะ หลังจากนั้นทุกคำสั่งที่เราพิมพ์ลงไปจะยังไม่ถูกบันทึกถาวรจนกว่าเราจะสั่งงาน
เมื่อมั่นใจว่าทุกอย่างถูกต้องแล้ว ให้ใช้ COMMIT (ยืนยันการบันทึก) เพื่อสั่งให้ฐานข้อมูลเขียนข้อมูลทั้งหมดลงไปจริงๆ หากระหว่างทางเกิดข้อผิดพลาด หรือคุณเปลี่ยนใจอยากยกเลิก ให้ใช้ ROLLBACK (ย้อนกลับข้อมูล) เพื่อล้างทุกอย่างที่ทำไปในช่วง BEGIN ทิ้งทันที
ข้อควรระวังคือ ถ้าคุณลืมปิดธุรกรรมด้วย COMMIT หรือ ROLLBACK ข้อมูลจะค้างอยู่ในสถานะ Pending (รอการยืนยัน) ทำให้คนอื่นไม่เห็นข้อมูลล่าสุดที่คุณเพิ่งอัปเดตไป
-- เริ่มต้นชุดคำสั่ง
BEGIN;
-- ลดเงินในบัญชี A
UPDATE accounts SET balance = balance - 500 WHERE id = 1;
-- เพิ่มเงินในบัญชี B
UPDATE accounts SET balance = balance + 500 WHERE id = 2;
-- บันทึกการเปลี่ยนแปลงทั้งหมด
COMMIT;
บรรทัดที่ใช้ BEGIN คือจุดเริ่ม UPDATE สองบรรทัดคือการแก้ไขข้อมูล และ COMMIT คือการสั่งเซฟ ผลลัพธ์คือยอดเงินของบัญชีทั้งสองจะเปลี่ยนพร้อมกันอย่างถูกต้อง
การใช้ SAVEPOINT เพื่อแบ่งจุดพักข้อมูล
บางครั้งธุรกรรมหนึ่งชุดอาจมีขั้นตอนยาวมาก คุณอาจอยากเซฟไว้เป็นระยะๆ เพื่อให้ย้อนกลับได้เฉพาะจุด SAVEPOINT (จุดบันทึกย่อย) ช่วยให้คุณย้อนกลับแค่บางส่วนได้โดยไม่ต้องยกเลิกทั้งธุรกรรมทั้งหมด
มันเหมือนกับการเล่นเกมแล้วกดเซฟเกมไว้ก่อนสู้กับบอส ถ้าคุณสู้แพ้ คุณไม่ต้องเริ่มเล่นใหม่ตั้งแต่ต้น แต่กลับมาเริ่มที่หน้าบอสได้เลย ROLLBACK TO (ย้อนกลับไปยังจุดบันทึก) คือคำสั่งที่จะช่วยคุณทำสิ่งนี้
มือใหม่มักจะใช้ ROLLBACK แบบเหมารวมจนเสียงานทั้งหมดไป ให้ฝึกใช้จุดบันทึกเมื่อต้องทำขั้นตอนที่ซับซ้อน จะช่วยลดความเครียดเวลาเจอข้อผิดพลาดกลางคันได้ดีมาก
BEGIN;
INSERT INTO logs (msg) VALUES ('เริ่มทำรายการ');
SAVEPOINT step1;
UPDATE items SET stock = stock - 1 WHERE id = 10;
-- ถ้าเกิดบั๊กที่นี่ เราย้อนกลับแค่การอัปเดต stock ได้
ROLLBACK TO step1;
COMMIT;
บรรทัด SAVEPOINT step1 คือการสร้างจุดพัก ROLLBACK TO step1 คือการสั่งให้ระบบลบแค่การอัปเดตสินค้าทิ้ง แต่ข้อความในตาราง logs ยังคงอยู่ ผลลัพธ์คือข้อมูลใน logs จะถูกบันทึก แต่ยอดสินค้าจะเท่าเดิม
รู้จักกับ Isolation Levels เพื่อความปลอดภัยของข้อมูล
เมื่อมีคนใช้งานฐานข้อมูลพร้อมกันหลายคน ปัญหาที่ชื่อว่า Isolation Levels (ระดับการแยกธุรกรรม) จะเริ่มมีความสำคัญ การตั้งค่านี้จะกำหนดว่าธุรกรรมของคุณจะมองเห็นการเปลี่ยนแปลงของคนอื่นได้แค่ไหน
ระดับที่เบาสุดคือ Read Committed (อ่านข้อมูลที่ยืนยันแล้ว) ซึ่งเป็นค่ามาตรฐานของ PostgreSQL มันช่วยให้คุณเห็นเฉพาะข้อมูลที่ถูก COMMIT ไปแล้วเท่านั้น ส่วนระดับที่เข้มข้นที่สุดคือ Serializable (การเรียงลำดับธุรกรรม) ที่ป้องกันความผิดพลาดได้สูงสุด
การเลือกใช้ระดับที่สูงเกินไปอาจทำให้ฐานข้อมูลทำงานช้าลงเพราะต้องรอคิวกัน ให้เลือกระดับที่เหมาะสมกับประเภทของแอปที่คุณกำลังพัฒนาเป็นหลัก
ปัญหาที่พบบ่อยและวิธีแก้ไขสำหรับมือใหม่
ปัญหาคลาสสิกที่โปรแกรมเมอร์มือใหม่เจอคือ Deadlock (ภาวะชะงักงัน) ซึ่งเกิดจากสองธุรกรรมพยายามแย่งล็อกข้อมูลกันเอง ทำให้ระบบค้างและทำงานต่อไม่ได้ คุณต้องเขียนโค้ดให้จัดการกับข้อผิดพลาดนี้เสมอ
วิธีแก้ที่ดีที่สุดคือการเรียงลำดับการเข้าถึงข้อมูลให้เหมือนกันทุกจุด หรือใช้ SELECT ... FOR UPDATE (จองข้อมูลไว้ก่อนอัปเดต) เพื่อบอกฐานข้อมูลว่าเรากำลังจะแก้ไขแถวนี้ ใครอย่าเพิ่งมายุ่ง
หมั่นตรวจสอบสถานะของฐานข้อมูลผ่าน Terminal (หน้าจอพิมพ์คำสั่ง) อยู่เสมอ หากเจอคำสั่งที่ค้างนานเกินไป ให้ลองไล่ดูว่าเราลืม COMMIT หรือเปล่า มันเป็นจุดที่พลาดกันได้ง่ายที่สุด
สรุปการนำไปใช้จริงในโปรเจกต์ของคุณ
การบริหารจัดการธุรกรรมไม่ใช่เรื่องยากถ้าคุณฝึกจนเป็นนิสัย ทุกครั้งที่ต้องเขียนโค้ดแก้ไขข้อมูลหลายตารางพร้อมกัน จงใช้ BEGIN และ COMMIT เสมอ เพื่อป้องกันข้อมูลพัง
ลองทำโปรเจกต์จำลองระบบธนาคารเล็กๆ ในคอมพิวเตอร์ของคุณดูครับ ลองโอนเงินแล้วทดลองสั่ง ROLLBACK ดูว่าเงินจะย้อนกลับมาที่เดิมไหม การทดลองด้วยตัวเองจะทำให้คุณเข้าใจหัวใจสำคัญของฐานข้อมูลได้ดีกว่าการอ่านทฤษฎีแน่นอน
เริ่มจากโปรเจกต์เล็กๆ ที่ใช้งานจริง 1 อย่าง แล้วนำความรู้นี้ไปใส่ไว้ในโค้ดของคุณ เมื่อคุณทำจนคล่อง คุณจะก้าวข้ามผ่านความเป็นมือใหม่และกลายเป็นโปรแกรมเมอร์ที่เขียนโค้ดได้อย่างมั่นใจและปลอดภัยมากขึ้น