ในโลกของระบบองค์กร (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 ข้อมูลย้อนหลังทำได้อย่างรวดเร็วและยืดหยุ่น