Audit

ในโลกของระบบองค์กร (Enterprise System) ข้อมูลไม่ใช่แค่สินทรัพย์ แต่คือความน่าเชื่อถือ (Trust) การทำ Audit หรือการตรวจสอบข้อมูลจึงเป็นกลไกเชิงป้องกันที่สำคัญที่สุดสำหรับ Senior Architect ทุกคน การ Audit ในบริบทของฐานข้อมูล ไม่ใช่แค่การตรวจสอบว่าข้อมูลผิดพลาดหรือไม่ แต่คือการสร้างหลักฐานที่ตรวจสอบย้อนกลับได้ (Audit Trail) ว่าใคร (Who) ได้ทำอะไร (What) กับข้อมูลสำคัญเมื่อไหร่ (When) และทำไม (Why)

🔍 Audit คืออะไรใน PostgreSQL?

ในทางเทคนิค การทำ Audit ใน PostgreSQL คือการสร้างระบบบันทึก (Logging) ที่ติดตามทุกการดำเนินการระดับแถว (Row-level) ไม่ว่าจะเป็นการสร้าง (INSERT), การอ่าน (SELECT), การแก้ไข (UPDATE), หรือการลบ (DELETE) โดยการใช้ฟีเจอร์ที่ทรงพลังอย่าง Triggers และ Stored Functions เพื่อให้ข้อมูลการเปลี่ยนแปลงถูกบันทึกลงในตาราง Audit แยกต่างหาก

วัตถุประสงค์เชิงสถาปัตยกรรม (Architectural Goals)

  • การปฏิบัติตามข้อกำหนด (Compliance): ตอบโจทย์มาตรฐานสากล เช่น GDPR หรือ HIPAA ที่ต้องการหลักฐานการเข้าถึงข้อมูลส่วนบุคคล
  • Accountability: ระบุตัวตนผู้ใช้ที่รับผิดชอบการเปลี่ยนแปลงข้อมูลได้อย่างชัดเจน
  • Forensics: ใช้ในการสืบสวนหาต้นตอของการทุจริตหรือข้อมูลที่สูญหาย

⚙️ การสร้าง Audit Trail ด้วย PostgreSQL Triggers

วิธีที่แม่นยำและมีประสิทธิภาพที่สุดในการทำ Audit ในระดับฐานข้อมูลคือการใช้ Triggers เพราะมันจะทำงานโดยอัตโนมัติ (Automatic) ทันทีที่คำสั่ง DML (Data Manipulation Language) ถูกเรียกใช้ โดยเราจะสร้างฟังก์ชัน (Function) ที่รับผิดชอบการบันทึกข้อมูล และผูกฟังก์ชันนั้นเข้ากับตารางเป้าหมายด้วย Trigger

ขั้นตอนการติดตั้ง (Implementation Steps)

สมมติว่าเรามีตาราง `products` และต้องการบันทึกทุกการเปลี่ยนแปลงลงในตาราง `audit_log`

SQL

-- 1. สร้างตารางหลักที่ต้องการ Audit (Source Table) 
CREATE TABLE products (
    product_id SERIAL PRIMARY KEY,
    product_name VARCHAR(100) NOT NULL,
    price NUMERIC(10, 2)
);

-- 2. สร้างตารางสำหรับเก็บ Audit Log 
CREATE TABLE audit_log (
    log_id SERIAL PRIMARY KEY,
    table_name VARCHAR(50) NOT NULL,
    operation_type VARCHAR(10) NOT NULL, -- INSERT, UPDATE, DELETE
    old_data JSONB,
    new_data JSONB,
    changed_by TEXT DEFAULT CURRENT_USER,
    changed_at TIMESTAMP DEFAULT NOW()
);

-- 3. สร้าง Trigger Function (Logic) 
CREATE OR REPLACE FUNCTION log_product_changes() RETURNS TRIGGER AS $$
BEGIN
    IF (TG_OP = 'INSERT') THEN
        INSERT INTO audit_log (table_name, operation_type, new_data) VALUES 
        ('products', 'INSERT', to_jsonb(NEW));
        RETURN NEW;
    ELSIF (TG_OP = 'UPDATE') THEN
        INSERT INTO audit_log (table_name, operation_type, old_data, new_data) VALUES 
        ('products', 'UPDATE', to_jsonb(OLD), to_jsonb(NEW));
        RETURN NEW;
    ELSIF (TG_OP = 'DELETE') THEN
        INSERT INTO audit_log (table_name, operation_type, old_data) VALUES 
        ('products', 'DELETE', to_jsonb(OLD));
        RETURN OLD;
    END IF;
    RETURN NULL;
END;$$
LANGUAGE plpgsql;

-- 4. ผูก Trigger เข้ากับตาราง products 
CREATE TRIGGER product_audit_trigger
AFTER INSERT OR UPDATE OR DELETE ON products
FOR EACH ROW
EXECUTE FUNCTION log_product_changes();

💡 การทำงานของโค้ด (Deep Dive)

เมื่อโค้ดนี้ถูกรัน ระบบจะสร้าง Trigger ที่ทำงานหลังการดำเนินการ (AFTER) บนตาราง `products` โดยใช้ฟังก์ชัน `log_product_changes()` ภายในฟังก์ชันนี้จะใช้ตัวแปรพิเศษของ PostgreSQL คือ `OLD` (ข้อมูลก่อนการเปลี่ยนแปลง) และ `NEW` (ข้อมูลหลังการเปลี่ยนแปลง) เพื่อบันทึกรายละเอียดการดำเนินการทั้งหมดลงใน `audit_log` โดยอัตโนมัติ นี่คือการรับประกันความสมบูรณ์ของข้อมูลในระดับสถาปัตยกรรมที่สูงมาก

✅ บทสรุปสำหรับ Senior Architect

การใช้ PostgreSQL Triggers สำหรับการทำ Audit ไม่เพียงแต่ช่วยให้คุณบรรลุข้อกำหนดด้าน Compliance เท่านั้น แต่ยังเป็นการเพิ่มชั้นความปลอดภัยที่ยากต่อการหลีกเลี่ยง (Hardened Security Layer) ให้กับระบบของคุณ การออกแบบ Audit Trail ที่ดีต้องคำนึงถึงประสิทธิภาพ (Performance) ด้วย ดังนั้นควรพิจารณาการเก็บข้อมูล Log ในรูปแบบที่เหมาะสม เช่น JSONB เพื่อให้การ Query ข้อมูลย้อนหลังทำได้อย่างรวดเร็วและยืดหยุ่น