BEGIN TRANSACTION, COMMIT, ROLLBACK: การจัดการ Transaction ใน MySQL อย่างละเอียด
ในบทก่อนหน้า เราได้เรียนรู้เกี่ยวกับ Transaction และความสำคัญของมันในการรักษาความสมบูรณ์ของข้อมูลในฐานข้อมูล MySQL บทนี้จะเจาะลึกถึงคำสั่ง SQL ที่ใช้ในการจัดการ Transaction ได้แก่ BEGIN TRANSACTION, COMMIT และ ROLLBACK พร้อมทั้งแนวทางการจัดการข้อผิดพลาดที่อาจเกิดขึ้นระหว่าง Transaction
BEGIN TRANSACTION: จุดเริ่มต้นของ Transaction
คำสั่ง BEGIN TRANSACTION (หรือ START TRANSACTION ซึ่งมีความหมายเดียวกัน) เป็นคำสั่งแรกที่เราต้องใช้ในการเริ่มต้น Transaction ใหม่ คำสั่งนี้จะบอกให้ MySQL Server เริ่มต้นบันทึกการเปลี่ยนแปลงที่จะเกิดขึ้นกับฐานข้อมูล แต่ยังไม่ทำการบันทึกจริงจนกว่าจะได้รับคำสั่ง COMMIT
BEGIN TRANSACTION;
-- หรือ
START TRANSACTION;
เหตุผลเชิงออกแบบ: การใช้ BEGIN TRANSACTION ทำให้เราสามารถรวบรวมชุดคำสั่ง SQL หลายคำสั่งไว้ภายใต้หน่วยการทำงานเดียวกัน หากคำสั่งใดคำสั่งหนึ่งล้มเหลว เราสามารถยกเลิกการเปลี่ยนแปลงทั้งหมดได้ ทำให้มั่นใจได้ว่าข้อมูลในฐานข้อมูลจะอยู่ในสถานะที่ถูกต้องเสมอ
ตัวอย่าง: สมมติว่าเราต้องการโอนเงินจากบัญชี A ไปยังบัญชี B เราต้องทำสองขั้นตอน: ลดเงินในบัญชี A และเพิ่มเงินในบัญชี B หากขั้นตอนใดขั้นตอนหนึ่งล้มเหลว เราไม่ต้องการให้เกิดการเปลี่ยนแปลงใดๆ ในฐานข้อมูล
BEGIN TRANSACTION;
-- ลดเงินในบัญชี A
UPDATE accounts SET balance = balance - 100 WHERE account_id = 'A';
-- เพิ่มเงินในบัญชี B
UPDATE accounts SET balance = balance + 100 WHERE account_id = 'B';
-- หากทุกอย่างเรียบร้อย ให้ COMMIT
COMMIT;
-- หากมีข้อผิดพลาด ให้ ROLLBACK
-- ROLLBACK;
COMMIT: บันทึกการเปลี่ยนแปลง
เมื่อการดำเนินการทั้งหมดภายใน Transaction เสร็จสมบูรณ์และไม่มีข้อผิดพลาดเกิดขึ้น เราจะใช้คำสั่ง COMMIT เพื่อบันทึกการเปลี่ยนแปลงทั้งหมดลงในฐานข้อมูลอย่างถาวร
COMMIT;
เหตุผลเชิงออกแบบ: COMMIT ทำให้มั่นใจได้ว่าข้อมูลที่เปลี่ยนแปลงภายใน Transaction จะถูกบันทึกลงในฐานข้อมูลอย่างถาวร และสามารถมองเห็นได้โดยผู้ใช้อื่นๆ
ROLLBACK: ยกเลิกการเปลี่ยนแปลง
หากมีข้อผิดพลาดเกิดขึ้นระหว่าง Transaction หรือเราต้องการยกเลิกการเปลี่ยนแปลงทั้งหมด เราจะใช้คำสั่ง ROLLBACK คำสั่งนี้จะยกเลิกการเปลี่ยนแปลงทั้งหมดที่เกิดขึ้นตั้งแต่ BEGIN TRANSACTION และคืนค่าฐานข้อมูลกลับสู่สถานะเดิมก่อนที่จะเริ่ม Transaction
ROLLBACK;
เหตุผลเชิงออกแบบ: ROLLBACK เป็นกลไกสำคัญในการรักษาความสมบูรณ์ของข้อมูล หากเกิดข้อผิดพลาดที่ไม่คาดฝันขึ้น เราสามารถยกเลิกการเปลี่ยนแปลงทั้งหมดเพื่อป้องกันไม่ให้ข้อมูลเสียหาย
การจัดการข้อผิดพลาดภายใน Transaction
การจัดการข้อผิดพลาดเป็นส่วนสำคัญของการใช้ Transaction เพื่อให้มั่นใจว่าเราสามารถตรวจจับและจัดการกับข้อผิดพลาดที่อาจเกิดขึ้นได้อย่างเหมาะสม
แนวปฏิบัติที่ดี:
- ใช้ TRY...CATCH (หรือเทียบเท่าในภาษาโปรแกรมของคุณ): หากคุณกำลังใช้ภาษาโปรแกรมเพื่อเชื่อมต่อกับ MySQL คุณควรใช้บล็อก
TRY...CATCHเพื่อดักจับข้อผิดพลาดที่อาจเกิดขึ้นระหว่าง Transaction - ตรวจสอบผลลัพธ์ของคำสั่ง SQL: หลังจาก execute แต่ละคำสั่ง SQL ให้ตรวจสอบว่าคำสั่งนั้นสำเร็จหรือไม่ หากมีข้อผิดพลาดเกิดขึ้น ให้ทำการ
ROLLBACK - บันทึกข้อผิดพลาด: บันทึกข้อผิดพลาดที่เกิดขึ้นระหว่าง Transaction เพื่อช่วยในการแก้ไขปัญหาในอนาคต
ตัวอย่าง (โดยใช้ภาษา PHP):
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "database";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// begin the transaction
$conn->beginTransaction();
// our SQL statements
$conn->exec("UPDATE accounts SET balance = balance - 100 WHERE account_id = 'A'");
$conn->exec("UPDATE accounts SET balance = balance + 100 WHERE account_id = 'B'");
// commit the transaction
$conn->commit();
echo "Transaction completed successfully";
} catch(PDOException $e) {
// rollback the transaction if something failed
$conn->rollback();
echo "Error: " . $e->getMessage();
}
$conn = null;
?>
คำอธิบาย:
- เราใช้
try...catchเพื่อดักจับPDOExceptionซึ่งอาจเกิดขึ้นหากมีข้อผิดพลาดในการเชื่อมต่อหรือ execute คำสั่ง SQL - ภายใน
tryblock เราเริ่มต้น Transaction ด้วย$conn->beginTransaction() - เรา execute คำสั่ง SQL สองคำสั่งเพื่อโอนเงิน
- หากไม่มีข้อผิดพลาดเกิดขึ้น เรา commit Transaction ด้วย
$conn->commit() - หากมีข้อผิดพลาดเกิดขึ้น เรา rollback Transaction ด้วย
$conn->rollback()และแสดงข้อความแสดงข้อผิดพลาด
Isolation Levels (ระดับความเป็นอิสระ)
MySQL รองรับ Isolation Levels หลายระดับ ซึ่งกำหนดระดับความเป็นอิสระระหว่าง Transaction ต่างๆ Isolation Levels ที่พบบ่อยได้แก่:
- READ UNCOMMITTED: เป็นระดับที่อิสระน้อยที่สุด Transaction สามารถอ่านข้อมูลที่ยังไม่ได้รับการ commit จาก Transaction อื่นๆ (Dirty Reads)
- READ COMMITTED: Transaction สามารถอ่านข้อมูลที่ได้รับการ commit แล้วเท่านั้น ป้องกัน Dirty Reads
- REPEATABLE READ (Default): Transaction จะเห็น snapshot ของข้อมูล ณ เวลาที่เริ่มต้น Transaction ป้องกัน Dirty Reads และ Non-Repeatable Reads
- SERIALIZABLE: เป็นระดับที่อิสระมากที่สุด Transaction จะทำงานเหมือนกับว่าไม่มี Transaction อื่นๆ ทำงานพร้อมกัน ป้องกัน Dirty Reads, Non-Repeatable Reads และ Phantom Reads
คุณสามารถตั้งค่า Isolation Level ได้โดยใช้คำสั่ง:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
เหตุผลเชิงออกแบบ: การเลือก Isolation Level ที่เหมาะสมเป็นสิ่งสำคัญเพื่อให้ได้สมดุลระหว่างความถูกต้องของข้อมูลและประสิทธิภาพของระบบ Isolation Level ที่สูงขึ้นจะให้ความถูกต้องของข้อมูลมากขึ้น แต่ก็อาจทำให้ประสิทธิภาพลดลง
สรุป
ในบทนี้ เราได้เรียนรู้เกี่ยวกับคำสั่ง BEGIN TRANSACTION, COMMIT และ ROLLBACK ซึ่งเป็นเครื่องมือสำคัญในการจัดการ Transaction ใน MySQL เรายังได้เรียนรู้เกี่ยวกับแนวทางการจัดการข้อผิดพลาดและ Isolation Levels เพื่อให้มั่นใจว่าข้อมูลในฐานข้อมูลของเรามีความถูกต้องและสอดคล้องกันเสมอ ในบทต่อไป เราจะเรียนรู้เกี่ยวกับการจัดการ User และ Permissions ใน MySQL