ป้ายกำกับ: Mvcc

MVCC Mechanics (Multi-Version Concurrency Control & Tuple Versioning)MVCC Mechanics (Multi-Version Concurrency Control & Tuple Versioning)

ในระบบฐานข้อมูลสมัยใหม่ที่รองรับผู้ใช้งานจำนวนมากพร้อมกัน (High Concurrency) ปัญหาหลักที่ต้องแก้ไขคือการรับประกันความสอดคล้องของข้อมูล (Data Consistency) และการจัดการการเข้าถึงทรัพยากรพร้อมกัน (Concurrency Control) หากไม่มีกลไกที่เหมาะสม การที่ผู้ใช้คนหนึ่งกำลังอ่านข้อมูล ในขณะที่อีกคนกำลังแก้ไขข้อมูลนั้น อาจทำให้เกิดการอ่านค่าที่ไม่สมบูรณ์หรือขัดแย้งได้

นี่คือจุดที่ Multi-Version Concurrency Control (MVCC) เข้ามามีบทบาท MVCC ไม่ได้แก้ปัญหาด้วยการ ‘ล็อก’ ทรัพยากรทั้งหมด แต่เปลี่ยนแนวคิดจากการ ‘เขียนทับ’ (Overwriting) ข้อมูลไปเป็นการ ‘สร้างเวอร์ชันใหม่’ (Versioning) เมื่อมีการเปลี่ยนแปลงข้อมูล

💡 หลักการทำงานของ MVCC ใน PostgreSQL

หัวใจหลักของ MVCC คือการที่ PostgreSQL ไม่ลบข้อมูลเก่าทิ้งทันทีเมื่อมีการอัปเดต (UPDATE) หรือลบ (DELETE) แต่จะเก็บสำเนาของข้อมูลนั้นไว้ในรูปแบบของ ‘เวอร์ชัน’ (Tuples) พร้อมกับเมตาดาต้าสำคัญ เช่น Transaction ID (TxID) ที่ระบุว่าเวอร์ชันนี้ถูกสร้างขึ้นเมื่อไหร่ และเวอร์ชันนี้มีผลถึงเมื่อไหร่

เมื่อ Transaction A เริ่มต้นขึ้น มันจะได้รับ ‘ภาพรวม’ ของข้อมูล ณ เวลาที่มันเริ่มทำงาน (Snapshot Isolation) และจะไม่ถูกรบกวนจากการเขียนของ Transaction B ที่เกิดขึ้นภายหลัง ทำให้ Transaction A สามารถอ่านข้อมูลที่สอดคล้องกับช่วงเวลาของตัวเองได้โดยสมบูรณ์ ซึ่งช่วยให้เกิดความสามารถในการอ่านที่สอดคล้องสูงมาก (High Read Consistency) โดยที่ระบบแทบไม่ต้องใช้การล็อกระดับแถว (Row-level Locking) ในการอ่านเลย

⚙️ ตัวอย่างกลไกการทำงานด้วย SQL (PostgreSQL)

สมมติว่าเรามีตาราง `products` และมีการอัปเดตข้อมูล:

SQL

-- 1. สร้างตาราง (มีคอลัมน์ที่เก็บเวอร์ชัน) 
CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    price NUMERIC
);

-- 2. ใส่ข้อมูลเริ่มต้น (Version 1)
INSERT INTO products (id, name, price) VALUES (1, 'apple', 1.00);

-- 3. Transaction B อัปเดตข้อมูล (สร้าง Version 2)
-- ข้อมูลเก่า (Version 1) ยังคงอยู่ แต่ถูกทำเครื่องหมายว่า 'ไม่ใช้งาน' สำหรับ TxID ใหม่
UPDATE products SET price = 1.20 WHERE id = 1;

-- 4. Transaction A (ที่เริ่มก่อนการอัปเดต) อ่านข้อมูล
-- PostgreSQL จะส่งมอบ Version 1 ให้ Transaction A เพื่อให้มั่นใจว่าข้อมูลที่อ่านมีความสอดคล้องกับช่วงเวลาของมัน
SELECT * FROM products WHERE id = 1;

จากตัวอย่างข้างต้น Transaction A จะยังคงเห็นราคา 1.00 (Version 1) ในขณะที่ Transaction C ที่เริ่มหลังจากนั้นจะเห็นราคา 1.20 (Version 2) นี่คือการรับประกันความสอดคล้องของข้อมูลที่ MVCC มอบให้

🚀 บทสรุป: ทำไม MVCC ถึงสำคัญต่อสถาปัตยกรรมระบบ

MVCC คือรากฐานสำคัญที่ทำให้ PostgreSQL มีประสิทธิภาพสูงและสามารถขยายขนาด (Scalability) ได้อย่างยอดเยี่ยมในสภาพแวดล้อมที่มีการเข้าถึงพร้อมกันสูง (High Concurrency) การที่ระบบสามารถแยกการอ่านออกจากกระบวนการเขียนได้อย่างมีประสิทธิภาพ ทำให้ Throughput ของระบบเพิ่มขึ้นอย่างมาก โดยที่นักพัฒนาไม่ต้องกังวลเรื่อง Deadlocks หรือการอ่านข้อมูลที่ขัดแย้งกัน