หลอมรวมทั้ง 4 เสาหลัก (UDFs + Procedures + Event Triggers + Materialized Views) พร้อมพลัง Set-Based Logic สู่สถาปัตยกรรม Unified In-Database Automation Engine ฉบับสมบูรณ์ แก้โจทย์ระบบชำระเงินและปิดยอดระดับ 100+ ล้านธุรกรรม/ปี ปลอดล็อกจาก Deadlock, ขจัด WAL Bloat, ป้องกันการทุจริตด้วย Zero-Bypass Audit และตอบสนองแดชบอร์ดใน 4 ms!
สี่เสาหลักเรียนแยกกันมาแล้ว วันนี้คือวันที่เอาทุกชิ้นมาประกอบเป็นระบบเดียวกัน แล้วดูว่าแต่ละส่วนส่งไม้ต่อกันอย่างไร
การนำองค์ความรู้ของสี่เสาหลัก — UDFs, Procedures, Triggers, Materialized Views — ที่เรียนแยกกัน มาประติดประต่อให้ทำงานร่วมกัน
การรีวิวสถาปัตยกรรมระบบจำลองขนาดใหญ่ เช่น ระบบการเงินหรืออีคอมเมิร์ซ แบบต้นทางถึงปลายทาง ว่าทุกส่วนเชื่อมต่อกันอย่างไร
โดยรวมวันนี้คือการสร้าง In-Database Automation Engine ฉบับสมบูรณ์ — UDF คำนวณ, Procedure ตัด chunk, Trigger บันทึก audit, และ Materialized View ทำรายงาน
สรุปจบท้าย Phase 2 ให้เห็นภาพใหญ่ว่าทั้งสี่เสาหลักทำงานส่งไม้ต่อกันอย่างไรในระบบ enterprise จริง ก่อนจะเข้า Phase 3 ที่พูดเรื่องดูแลโค้ดและเส้นแบ่งสถาปัตยกรรม
การเดินทางผ่าน Days 5–9 ทำให้เราเชี่ยวชาญเครื่องมือทั้ง 4 เสาหลักแบบแยกเดี่ยว แต่ในโลกจริงของระบบ Enterprise ระดับ Mission-Critical คำถามที่สถาปนิกและผู้บริหารระดับสูงมักถามเสมอคือ "เมื่อระบบเติบโตสู่ระดับ 100 ล้านธุรกรรม เราจะนำเสาหลักทั้งหมดนี้มาทำงานร่วมกันอย่างไรโดยไม่ให้เกิดการขัดแย้งกันเอง (Architectural Cohesion)?"
ระบบชำระเงินและปิดบัญชีประจำวัน (End-of-Day Financial Settlement Engine) ของแพลตฟอร์ม E-Commerce ขนาดใหญ่ มีธุรกรรมสะสมกว่า 100,000,000 รายการต่อปี สถาปัตยกรรมเดิมแยกชิ้นส่วนการทำงานอย่างกระจัดกระจาย: App สั่งเรียก UDF คำนวณส่วนลดสดๆ จากนั้นสั่ง UPDATE ตารางตรงๆ โดยไม่มี Audit Trail ใน DB, มีสคริปต์ภายนอกยิงวนลูปตัดเงินทีละแถว (RBAR) และผู้บริหารเรียกยิง Query สรุปยอดขายบนตารางจริงในเวลา 20.00 น.:
ต้นตอของวิกฤตนี้คือ Disjointed Architecture (สถาปัตยกรรมกระจัดกระจาย) ทางออกเดียวในระดับ Enterprise คือการร้อยเรียงทั้ง 4 เสาหลักเข้าด้วยกันเป็น Unified In-Database Automation Engine ครับ!
| มิติเปรียบเทียบสถาปัตยกรรม | สถาปัตยกรรมเดิม (Disjointed Legacy) | สถาปัตยกรรมใหม่ (Capstone Unified Engine) |
|---|---|---|
| ตรรกะการคำนวณราคาสุทธิ (Pricing) | คำนวณบน App หรือ UDF ที่เป็น VOLATILE (ช้า 2M ครั้ง) | Pillar 1 UDF: IMMUTABLE + SQL-Inlining (Native Speed) |
| การประมวลผล Batch ปิดยอด (Settlement) | RBAR Loop ทีละแถวใน Single Giant Transaction | Pillar 2 Procedure: Chunked COMMIT (10k rows) + SKIP LOCKED |
| การบันทึกประวัติความปลอดภัย (Audit) | เขียนบน App Code (ถูก Bypass ได้เมื่อยิง DB ตรง) | Pillar 3 Trigger: AFTER Trigger + JSONB Delta (Non-bypassable 100%) |
| รายงานวิเคราะห์ของผู้บริหาร (Dashboard) | สแกนสด 100M แถวบนตารางจริงในเวลา Peak (CPU 100%) | Pillar 4 MV: REFRESH CONCURRENTLY ผ่าน pg_cron (โหลดใน 4 ms) |
| เสถียรภาพเมื่อเกิดระบบ Crash กลางคัน | All-or-Nothing Rollback สูญเสียงานหลายชั่วโมงทิ้ง | Autonomous Resilience: ข้อมูล Chunk ที่ COMMIT แล้วปลอดภัย 100% |
"ทุกท่านครับ นี่คือ Capstone Architecture ที่สังเคราะห์ 4 เสาหลักเข้าด้วยกันเป็นหนึ่งเดียว!
เราไม่ได้แค่สร้าง Stored Unit ลอยๆ แต่เราใช้ UDF (IMMUTABLE) คำนวณส่วนลดแบบ Inlined, ใช้ Procedure (COMMIT Chunking) ปิดยอด 100 ล้านรายการโดย WAL ไม่บวม, ใช้ Trigger (AFTER + JSONB) ดัก Audit ความปลอดภัย 100% ไม่มีวันถูก Bypass, และใช้ Materialized View (pg_cron) เสิร์ฟแดชบอร์ดใน 4 มิลลิวินาที!
ผลลัพธ์คือสถาปัตยกรรมฐานข้อมูลที่ทรงพลัง เสถียร รองรับ Concurrency สูงสุด และพร้อมสำหรับระบบ Enterprise ระดับ Mission-Critical ครับ!"
ลองเลือกสถาปัตยกรรมการบูรณาการ และปรับขนาด Transaction Volume เพื่อเปรียบเทียบเวลาประมวลผล, สถานะ WAL Bloat, และการรอดชีวิตของระบบเมื่อเกิด Failure
การร้อยเรียงทั้ง 4 เสาหลักเข้าด้วยกันเป็น Capstone Architecture ต้องเข้าใจวิธีที่แต่ละส่วนส่งมอบงานให้กัน: เริ่มจาก Pillar 1 (UDF) คำนวณค่า, ถูกเรียกใช้โดย Pillar 2 (Procedure) ที่ประมวลผลแบบ Chunk, ทริกเกอร์ Pillar 3 (Trigger) ให้บันทึก Audit, และปิดท้ายด้วยการรีเฟรช Pillar 4 (Materialized View):
-- 🎯 [Pillar 1: Pure Calculation UDF] -> เปิดทาง Inlining
CREATE OR REPLACE FUNCTION fn_calc_net(p_amount NUMERIC, p_tax_rate NUMERIC)
RETURNS NUMERIC LANGUAGE sql IMMUTABLE STRICT AS $$
SELECT ROUND(p_amount * (1 + p_tax_rate), 2);
$$;
-- 🎯 [Pillar 3: Audit Trail Trigger Engine] -> Non-bypassable Compliance
CREATE OR REPLACE FUNCTION fn_trg_capstone_audit() RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN
INSERT INTO audit_logs(table_name, operation, old_data, new_data)
VALUES (TG_TABLE_NAME, TG_OP, to_jsonb(OLD), to_jsonb(NEW));
RETURN NULL;
END $$;
-- 🎯 [Pillar 4: Materialized View Pre-computation] -> Non-blocking Reporting
CREATE MATERIALIZED VIEW mv_capstone_sales_summary AS
SELECT DATE(created_at) AS sale_date, SUM(net_amount) AS total_revenue
FROM orders GROUP BY DATE(created_at) WITH DATA;
CREATE UNIQUE INDEX idx_mv_capstone_pk ON mv_capstone_sales_summary(sale_date);
-- 🎯 [Pillar 2: Stored Procedure Batch Settlement] -> Chunked Transaction Control
CREATE OR REPLACE PROCEDURE pr_capstone_settlement_batch(p_chunk_size INT DEFAULT 10000)
LANGUAGE plpgsql AS $$
DECLARE v_count INT := 0;
BEGIN
LOOP
WITH target_chunk AS (
SELECT id FROM orders WHERE status = 'PENDING' LIMIT p_chunk_size FOR UPDATE SKIP LOCKED
), updated_rows AS (
UPDATE orders o SET status = 'SETTLED', net_amount = fn_calc_net(o.amount, 0.07)
FROM target_chunk t WHERE o.id = t.id RETURNING o.id
)
SELECT COUNT(*) INTO v_count FROM updated_rows;
IF v_count = 0 THEN EXIT; END IF;
COMMIT; -- 🎯 Explicit Transaction Boundary Control
END LOOP;
END $$;
-- [1] ตาราง orders หลัก
CREATE TABLE IF NOT EXISTS orders (
id BIGSERIAL PRIMARY KEY,
customer_id INT NOT NULL,
amount NUMERIC(12,2) NOT NULL,
net_amount NUMERIC(12,2),
status VARCHAR(20) DEFAULT 'PENDING',
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
-- [2] Pillar 1: UDF คำนวณราคาสุทธิ (Pure Function Inlining)
CREATE OR REPLACE FUNCTION fn_calculate_net_price(p_amount NUMERIC)
RETURNS NUMERIC LANGUAGE sql IMMUTABLE STRICT AS $$
SELECT ROUND(p_amount * 1.07, 2);
$$;
-- [3] ตาราง Audit Logs สำหรับ Pillar 3
CREATE TABLE IF NOT EXISTS audit_logs (
audit_id BIGSERIAL PRIMARY KEY,
table_name VARCHAR(50) NOT NULL,
operation VARCHAR(10) NOT NULL,
old_data JSONB,
new_data JSONB,
changed_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
-- [4] Pillar 3: Trigger ดักจับ Audit ทุกการอัปเดตใน orders
CREATE OR REPLACE FUNCTION fn_trg_capstone_audit() RETURNS TRIGGER LANGUAGE plpgsql AS $$
BEGIN
INSERT INTO audit_logs(table_name, operation, old_data, new_data)
VALUES (TG_TABLE_NAME, TG_OP, to_jsonb(OLD), to_jsonb(NEW));
RETURN NULL;
END $$;
CREATE TRIGGER trg_audit_orders_change
AFTER UPDATE OR DELETE ON orders
FOR EACH ROW EXECUTE FUNCTION fn_trg_capstone_audit();
-- [1] Pillar 4: Materialized View สรุปยอดขายรายวัน (HTAP Light)
CREATE MATERIALIZED VIEW mv_daily_financial_report AS
SELECT
DATE(created_at) AS transaction_date,
COUNT(id) AS total_settled_orders,
SUM(net_amount) AS total_net_revenue
FROM orders
WHERE status = 'SETTLED'
GROUP BY DATE(created_at)
WITH DATA;
-- [2] สร้าง Unique Index บังคับสำหรับ Concurrent Refresh
CREATE UNIQUE INDEX idx_mv_daily_fin_pk ON mv_daily_financial_report (transaction_date);
-- [3] ตั้งเวลา pg_cron สั่งรีเฟรชทุกๆ 15 นาที
SELECT cron.schedule(
'cron_capstone_mv_refresh',
'*/15 * * * *',
'REFRESH MATERIALIZED VIEW CONCURRENTLY mv_daily_financial_report'
);
เปรียบเทียบโค้ดเดิมที่เป็น RBAR Loop ใน Single Transaction ที่ทำระบบพัง กับโค้ดใหม่ที่เป็น Full Capstone Enterprise Engine ที่บูรณาการครบ 4 เสาหลัก:
-- ❌ Flawed: รันใน Single Transaction, ใช้ RBAR Loop, ไม่มี Audit DB, ช้าและเสี่ยง Rollback ทั้งหมด
CREATE OR REPLACE FUNCTION fn_process_settlement_flawed()
RETURNS VOID LANGUAGE plpgsql AS $$
DECLARE
v_rec RECORD;
BEGIN
-- RBAR Anti-Pattern: วนลูป 100 ล้านรายการทีละแถวใน Single Transaction!
FOR v_rec IN SELECT id, amount FROM orders WHERE status = 'PENDING' LOOP
UPDATE orders
SET status = 'SETTLED',
net_amount = v_rec.amount * 1.07
WHERE id = v_rec.id;
-- 🚨 ไม่มี COMMIT! ถือ Lock ค้าง, WAL บวม 200GB
-- และถ้าพังแถวสุดท้ายจะ Rollback ทั้งหมดทิ้ง เสียเวลาฟรี!
END LOOP;
END $$;
-- [Statement 1] สร้าง Stored Procedure ควบคุม Batch Settlement ปริมาณมหาศาล
CREATE OR REPLACE PROCEDURE pr_capstone_settlement_engine(
p_batch_size INT DEFAULT 10000 -- ขนาด Chunk ละ 10,000 แถว
)
LANGUAGE plpgsql
AS $$
DECLARE
-- [บรรทัดที่ 1-3] ประกาศตัวแปรติดตามจำนวนแถวและเวลา
v_chunk_count INT := 0;
v_total_count INT := 0;
v_start_time TIMESTAMPTZ := CURRENT_TIMESTAMP;
BEGIN
-- [บรรทัดที่ 4] ปรับใช้ Multi-Core Parallel Workers ใน Session
SET LOCAL max_parallel_workers_per_gather = 4;
LOOP
-- [บรรทัดที่ 5-18] ดึงข้อมูลเฉพาะ Chunk + SKIP LOCKED + อัปเดตผ่าน Set-Based Logic
WITH target_orders AS (
SELECT id, amount FROM orders
WHERE status = 'PENDING'
LIMIT p_batch_size
FOR UPDATE SKIP LOCKED -- ข้ามแถวที่ Worker ตัวอื่นกำลังทำอยู่
),
updated_orders AS (
UPDATE orders o
SET status = 'SETTLED',
-- 🎯 เรียกใช้ Pillar 1 UDF (Inlined Pure Function)
net_amount = fn_calculate_net_price(t.amount)
FROM target_orders t
WHERE o.id = t.id
RETURNING o.id
)
SELECT COUNT(*) INTO v_chunk_count FROM updated_orders;
-- [บรรทัดที่ 19-21] ออกจากลูปเมื่อไม่มีข้อมูลค้างชำระ
IF v_chunk_count = 0 THEN
EXIT;
END IF;
v_total_count := v_total_count + v_chunk_count;
-- 🎯 [บรรทัดที่ 22] Pillar 2 Explicit Transaction Control: COMMIT ตัด Chunk
-- ปลด Row Lock, Flush WAL, และทริกเกอร์ Pillar 3 AFTER Trigger บันทึก Audit Log ทันที!
COMMIT;
END LOOP;
-- [บรรทัดที่ 23-24] สั่งรีเฟรช Pillar 4 Materialized View แบบ Non-blocking หลังปิดยอดเสร็จ
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_daily_financial_report;
RAISE NOTICE 'Capstone Settlement Completed: % rows settled in %',
v_total_count, CURRENT_TIMESTAMP - v_start_time;
END $$;
-- [Statement 2] เรียกใช้งานผ่าน CALL
CALL pr_capstone_settlement_engine(10000);
แบบทดสอบวัดระดับความเข้าใจ Capstone Architecture Synthesis, การบูรณาการ 4 เสาหลัก (UDFs, Procedures, Triggers, Materialized Views), HTAP Light Isolation, และข้อสอบสะสมทบทวนครบทั้ง Days 1–9 คลิกเลือกคำตอบ ก, ข, ค, หรือ ง เพื่อดูผลลัพธ์และคำอธิบายอย่างละเอียดทันที
บทเรียน Day 10: Phase 2 Synthesis & Capstone Architectural Review ได้นำเรามาสู่หมุดหมายสำคัญในการสังเคราะห์องค์ความรู้จาก Phase 2 (Days 5–10) รวมทั้ง 4 เสาหลัก (UDFs, Procedures, Triggers, Materialized Views) และ Set-Based Vectorized Processing เข้าด้วยกันเป็น Capstone Enterprise Engine ซึ่งพิสูจน์แล้วว่าสามารถรองรับงานระดับ 100+ ล้านธุรกรรมได้อย่างมั่นคง เสถียร ปลอดภัย และมีประสิทธิภาพสูงสุด
ในวันถัดไป (Day 11: Database-as-Code with Flyway / Liquibase Migration Mechanics) เราจะไปเจาะลึกการนำ Stored Units ทั้งหมดที่เราสร้างขึ้น มาจัดทำเวอร์ชันควบคุม (Version Control), การแยกยุทธศาสตร์ Versioned (V__) vs Repeatable (R__), การตรวจจับ Schema Drift, และการนำเข้าสู่ CI/CD Pipeline อัตโนมัติ 100% ครับ!