กรณีศึกษา & บันทึกการแก้ปัญหาระบบ

ถอดบทเรียนกรณีศึกษาจริงจากการเข้าไปแก้ปัญหาความปลอดภัย และจูนประสิทธิภาพระบบฐานข้อมูลออราเคิลให้ลูกค้าองค์กร

หน้าแรก > กรณีศึกษา
⚙️ จูนประสิทธิภาพ (Performance Tuning) 10

บทนำ: วิกฤต Perfect Storm ในระบบ ERP

ในโลกของระบบฐานข้อมูลระดับ Enterprise ปัญหาร้ายแรงมักไม่ได้เกิดจากสาเหตุเดียว แต่เกิดจากหลายปัจจัยซ่อนเร้นมาบรรจบกันในเวลาเดียว นี่คือบันทึกการทำงานของทีมที่ปรึกษาที่เข้าสืบสวนคดี CPU Server พุ่ง 100% ต่อเนื่อง จนใช้งานไม่ได้

⏱️
ย้อนกลับไป 2 สัปดาห์ก่อนหน้า
💊 ยาแก้ปวดที่หมดฤทธิ์ (Data Purging)

ลูกค้าประเมินเบื้องต้นว่าสาเหตุเกิดจาก "ข้อมูลเยอะเกินไป" จึงทำการ Purge ลบข้อมูลบางส่วน ลดปริมาณจาก 1,000,000 แถว เหลือ 400,000 แถว แม้ว่าระบบจะกลับมารวดเร็วทันตาเห็นในช่วงแรก แต่เพียง 2 สัปดาห์ข้อมูลสะสมเพิ่มขึ้นอย่างรวดเร็ว และ CPU ก็พุ่งกลับมาชนเพดาน 100% อีกครั้ง ซึ่งเป็นข้อพิสูจน์ว่า การแก้ปัญหาที่ปลายเหตุ ไม่สามารถหยุดยั้งปัญหานี้ได้อย่างแท้จริง

🔍
Day 1: การสืบสวน
⚙️ ค้นพบ "ปัญหาซ้อนทับ" 3 ชั้น (The 3-Layer Bottleneck)

จากการวิเคราะห์ Execution Plan และ Business Logic เชิงลึก พบว่าวิกฤต CPU 100% เกิดจาก 3 ปัญหาร้ายแรงที่ขัดแย้งและหนุนเสริมกันอยู่:

Business Logic
ข้ามขั้นตอนปิด Job
ลูกค้าเลี่ยงการทำ Job Closing ใน Epicor เพราะเข้าใจว่าบัญชีจบที่ Oracle ERP ทำให้งานค้างในกลุ่ม Active Records สูงหลายล้านแถว
Application Query
Scalar UDF ฝังในคิวรี
คำสั่ง SQL เบื้องหลังมีการเรียกใช้งานฟังก์ชันพิเศษ (Scalar User Defined Function) ฝังอยู่ในเงื่อนไขการค้นหาหลัก
Database Engine
SQL Server 2016 Limit
ฐานข้อมูลรุ่น 2016 มีข้อจำกัดในการประมวลผล UDF ทำให้ Optimizer สับสน ไม่ดึง Index มาใช้ และบังคับรันแบบ Row-By-Row
🛠️
Day 2-3: ลงมือแก้ปัญหา
⚡ ทลายคอขวดทีละจุด เพื่อกู้เสถียรภาพระบบ

ทีมงานวางแผนการแก้ไขเป็นขั้นตอนเพื่อปลดล็อกประสิทธิภาพสูงสุด โดยไม่ต้องเสี่ยงลบข้อมูลดิบ:

  • Step 1: หยุดการสร้างขยะค้างท่อ (แก้ Business Logic)
    ประสานงานกับทีมโอเปอเรชันเพื่อบังคับใช้กระบวนการ "Job Closing" เมื่อผลิตเสร็จ และรันโปรเซส "Capture COS/WIP Activity" เพื่อล้างมูลค่างานระหว่างทำ (WIP) และลงบัญชีแยกประเภททั่วไป (GL) อย่างสมบูรณ์ ส่งผลให้ Active Records ที่ค้างสะสมเปลี่ยนสถานะ (WIPCleared = 1)
  • Step 2: ปลดล็อก Performance ทันที
    เมื่อปริมาณ Active Records ลดลงอย่างมหาศาล ฐานข้อมูลสามารถนำ Index กลับมาใช้งานสืบค้นข้อมูลได้ทันที ส่งผลให้ CPU ร่วงลงสู่สภาวะปกติและเสถียร
  • Step 3: วางแผนป้องกันถาวรในระยะยาว
    เสนอแผนอัปเกรดฐานข้อมูลเป็น SQL Server 2019+ เพื่อใช้งานฟีเจอร์ Scalar UDF Inlining ซึ่งจะช่วยแก้ไขจุดอ่อนของแอปพลิเคชันได้ในระยะยาว
💡
บทสรุปทางธุรกิจ
ทำไมต้องใช้ที่ปรึกษาที่มองเห็นภาพรวม (Full Overview)
💡

ความยั่งยืนที่เหนือกว่าการแก้ปัญหาปลายเหตุ

ปัญหาระบบขององค์กรขนาดใหญ่เชื่อมโยงกันเสมอ การลบข้อมูล (Purging) เป็นเพียงการประทังอาการชั่วคราว หากต้องการความเสถียรที่ถาวร ต้องวิเคราะห์ให้ครอบคลุมทั้งพฤติกรรมการใช้งาน Business Process, Application Code, และ Database Engine

"ระบบช้าจัง ขอเพิ่ม RAM อีกได้ไหม?"

นี่คือประโยคคลาสสิกเมื่อแอปพลิเคชันเริ่มมีปัญหาคอขวด แต่จากประสบการณ์กว่า 20 ปี เราพบว่า "การเพิ่ม Hardware ไม่ใช่ยาสารพัดนึกเสมอไป" เคสนี้พิสูจน์ว่า ความเข้าใจสถาปัตยกรรมสำคัญกว่าการถม Resource เพียงอย่างเดียว

🚨
ปัญหาที่พบ
👥 User แค่ 60 คน แต่ระบบหน่วงจนทำงานไม่ได้

ระบบเป็นสถาปัตยกรรมแบบ 3-Tier (Oracle 12c ➡️ GlassFish ➡️ Client Web) อาการผิดปกติคือเมื่อ Concurrent Users เกิน 60 คน แอปพลิเคชันจะหน่วงจนค้าง ทั้งที่ปกติ 60 sessions ถือว่าน้อยมากสำหรับ Oracle Database

การแก้ไขเบื้องต้น (ปลายเหตุ)
⚙️ ถมฮาร์ดแวร์ Scale-up RAM เป็น 96 GB (แต่ยังไม่หาย)

ทีมงานเดิมย้ายระบบจาก Solaris (RAM 32 GB) ไปรันบน Linux พร้อมอัปเกรดจัดเต็ม RAM 96 GB และปรับ SGA/PGA ตาม Advisor อย่างครบถ้วน แต่ระบบยังคงช้าและหน่วงเหมือนเดิมทุกประการ!

🔍
การวิเคราะห์เชิงลึก
📈 ค้นพบคอขวด "Logon Storm" จากการไม่ทำ Connection Pooling

ทีมที่ปรึกษาวิเคราะห์ Connection Behavior ระหว่างแอปพลิเคชันและฐานข้อมูล จนพบความผิดปกติ:

  • Dedicated Server Process: ทุกครั้งที่มี Request จากผู้ใช้งาน ระบบจะสร้าง OS Process ใหม่บนฐานข้อมูลเสมอ เนื่องจากโค้ดฝั่งแอปพลิเคชันเปิดและปิดการเชื่อมต่ออยู่ตลอดเวลา
  • Logon Storm & Context Switching: การสถาปนาการเชื่อมต่อใหม่นับร้อยครั้งพร้อมกันทำให้ CPU ต้องรับภาระมหาศาลในการทำ Handshake (การอัปเกรด RAM เป็น 96 GB จึงไม่ช่วยลด Overhead ตรงนี้ได้เลย)
ทางออกที่แท้จริง
⚡ สยบปัญหาด้วย Connection Pooling & Database Parameter Tuning

ทีมงานเข้าดำเนินการแก้ไขที่ต้นตอสถาปัตยกรรมการเชื่อมต่อของระบบ Java และ Oracle:

  • 1. ทำ Connection Pooling บน GlassFish:
    เปลี่ยนพฤติกรรมจาก "สร้างการเชื่อมต่อใหม่ทุกครั้ง" เป็น "สร้างเตรียมรอไว้และนำกลับมาใช้งานซ้ำ" ลดขั้นตอน Handshake และยกเลิกการสร้าง OS Process ซ้ำซ้อน
  • 2. ปรับจูนพารามิเตอร์ Oracle Database:
    ปรับค่า PROCESSES และ SESSIONS ให้รองรับ Max Pool Size ที่ตั้งไว้บน GlassFish เพื่อให้เซิร์ฟเวอร์จัดสรรทรัพยากรล่วงหน้าได้อย่างพอเหมาะ
  • ผลลัพธ์: อาการล่าช้าและหน่วงหายไปอย่างสมบูรณ์แบบ ระบบรองรับผู้ใช้งานได้ตามขีดความสามารถที่ควรจะเป็น
💡
บทสรุปทางเทคนิค
การจูนฐานข้อมูลต้องมองแบบ End-to-End
💡

มองภาพรวมระบบมากกว่าแค่การขยายเซิร์ฟเวอร์

Database Tuning ไม่ใช่เพียงการเพิ่ม RAM หรือปรับพารามิเตอร์หน่วยความจำเฉพาะจุด แต่ต้องอาศัย "ความเข้าใจแบบ End-to-End" ตั้งแต่โค้ดแอปพลิเคชัน, เครือข่ายการรับส่ง, ไปจนถึงสถาปัตยกรรมระดับล่างสุดของ Database Engine

บทนำ: เมื่อเพิ่มแรมเป็น 2 เท่าก็ยังทำงานไม่ได้

ในระบบฐานข้อมูลรุ่นเก่า เช่น Oracle 9i บ่อยครั้งที่ขีดจำกัดทางประสิทธิภาพไม่ได้เกิดจากความสามารถของตัวเครื่องเซิร์ฟเวอร์ แต่เกิดจากการกำหนดค่าพารามิเตอร์ภายใน การซื้อฮาร์ดแวร์ใหม่โดยไม่มีการทำ Instance Tuning เปรียบเสมือนการขยายถังน้ำแต่ท่อส่งน้ำยังมีขนาดเท่าเดิม

🚨
วิกฤตหน้างาน
⚙️ ระบบผลิตอืดเฉื่อยและค้าง (Freeze) จนสายการผลิตหยุดชะงัก

โรงงานประสบปัญหาระบบค้างบ่อยครั้งในสายการผลิต โดยเวลาประมวลผลต่อ 1 Batch เพิ่มขึ้นจากเดิม 30 วินาที กลายเป็นหลายสิบนาที จนระบบเกิดอาการค้าง ลูกค้าเพิ่มแรมจาก 1 GB เป็น 2 GB แต่ความเร็วยังคงช้าและค้างเหมือนเดิม

🔍
การวิเคราะห์หาสาเหตุ
📊 คอขวดจากการตั้งค่า Default Memory (SGA ค้างที่ 128 MB)

ทีมงานตรวจประเมินพารามิเตอร์ผ่านคำสั่ง show parameter และพบปัญหาระดับสถาปัตยกรรม:

  • SGA Default Limits: ผู้รับเหมาติดตั้งระบบในอดีตตั้งค่าหน่วยความจำ SGA (System Global Area) ไว้เป็นค่าเริ่มต้น (Default) เพียง 128 MB เท่านั้น
  • Workload ไม่สมดุล: เมื่อข้อมูลและทรานแซกชันสะสมเพิ่มขึ้นหลายสิบปี ขนาด SGA 128 MB กลายเป็นคอขวด และเนื่องจากไม่มีการปรับ Instance ให้รับรู้แรมใหม่ Oracle Database จึงไม่สามารถนำแรม 2 GB ที่เพิ่มเข้ามาใช้งานประมวลผลได้เลย
🛠️
ขั้นตอนการกู้ระบบ
⚡ ทำ Instance Tuning ปรับโอนแรมให้ดาต้าเบสใช้งานอย่างเต็มเม็ดเต็มหน่วย

ทีมที่ปรึกษาวางแผนปรับแต่งหน่วยความจำและตัวแปรผ่าน Parameter File (init.ora / spfile):

  • ปรับแต่งด้วย Buffer Cache Size Advisor: วิเคราะห์และปรับขนาด Buffer Cache เพื่อเพิ่มอัตราการเจอข้อมูลในแรม (Cache Hit Ratio) และลด Physical Reads
  • ขยายพื้นที่หน่วยความจำ SGA: ปรับขยาย SGA ให้สัมพันธ์กับแรม 2 GB โดยคำนวณภายใต้เงื่อนไข: Total SGA + Aggregate PGA Target + OS Memory <= Physical RAM เพื่อไม่ให้เกิด Overflow ไปใช้ Swap Space
📈
ผลลัพธ์ที่ได้
🚀 ระบบผลิตกลับมารวดเร็วและเสถียร โดยไม่ต้องลงทุนซื้อเซิร์ฟเวอร์ใหม่

หลังการปรับค่าและรีสตาร์ทระบบ เวลาประมวลผลต่อ 1 Batch ลดลงจากหลายสิบนาที กลับมาอยู่ในระดับ "วินาที" ตามปกติ อาการค้างหายไป 100% สายการผลิตเดินหน้าได้เต็มกำลัง และประหยัดงบประมาณลงทุนซื้อเซิร์ฟเวอร์ใหม่ได้อย่างคุ้มค่า

บทนำ: ประมวลผล CDR 40 ล้านรายการ/วัน แต่ระบบช้าจนงานไม่ทัน

ระบบ Local Interconnect (LIC) ของหน่วยงานโทรคมนาคมระดับชาติ ทำหน้าที่ประมวลผล Call Detail Record (CDR) สูงถึง 40 ล้านรายการต่อวัน และรองรับการสืบค้นเลขหมาย MNP กว่า 60–80 ล้านครั้งต่อวัน ผ่านการวิเคราะห์ AWR Report เชิงลึก ทีมพบว่าต้นตอปัญหาไม่ได้อยู่ที่ฮาร์ดแวร์ แต่เป็นปัญหาการตั้งค่าและการจัดการทรัพยากรภายใน

🚨
The Challenge — อาการของปัญหา
📉 2 กระบวนการหลักช้าลงอย่างหนัก — Rating และ Summary Process

ระบบเกิดความล่าช้าอย่างหนักใน 2 กระบวนการสำคัญ: Rating Process (ประมวลผลรายวัน) และ Summary Process (สรุปผลข้อมูล) จากการวิเคราะห์ CPU and Wait Time Tuning Dimensions พบว่าทั้งสอง Process ตกอยู่ในโซนแดง (Needs Instance/RAC Tuning) Wait time ทะลุ 74–75% แบบแปลว่าเพิ่ม CPU จะไม่ช่วยอะไรเลย

🔍
Root Cause Analysis — AWR Report เผยเหตุ 4 จุด
📊 ค้นหาปัญหาช่อน Wait Event ด้วยการวิเคราะห์ AWR Snapshot

ทีมผู้เชี่ยวชาญเก็บและวิเคราะห์ AWR Snapshot แล้วพบสาเหตุชัดเจน 4 จุด:

  • Scheduler ชนกัน (resmgr:cpu quantum = 22% of DB Time): Automated Job ของ Oracle เช่น dbms_stats.gather_database_stats ทำงานซ้อนทับกับช่วงเวลาที่ Process หลักกำลังทำงาน
  • Resource Manager ตั้งค่าไม่เหมาะสม: Resource Plan ที่ใช้อยู่กำหนดให้ LIC Process (อยู่ใน OTHER_GROUPS) ใช้ CPU ได้เพียง 70% สูงสุด แทนที่จะเป็น 100%
  • Parallelism คอขวด (PX qref latch = 12.37%): คำสั่ง SQL ใน Summary Process มี /*+ PARALLEL(2) */ Hint ฝังอยู่ ทำให้ Parallel Degree กินพิกัด CPU 2 Core ที่มีอยู่จนเต็มขีดจำกัด
  • ขาดการ Maintenance อย่างสม่ำเสมอ: ทำให้ Automated Job ต้องใช้เวลาทำงานนานเกินปกติ หนุนให้ปัญหาการชนกันรุนแรงขึ้น
🛠️
The Solution & Recommendations
⚡ ปลดล็อก 4 จุดคอขวด โดยไม่ต้องซื้ฮาร์ดแวร์เพิ่ม
  • Schedule Tuning: หลีกเลี่ยงไม่ให้ Process หลักทำงานทับซ้อนช่วง Default Maintenance Window ของ Oracle (จ.–ศ. 22:00–02:00 น.) เพื่อลดการแย่ง CPU
  • Resource Manager Tuning: กำหนด Resource Plan ใหม่ให้ LIC Process ดึง CPU ได้เต็ม 100% แทนที่จะถูกจำกัดไว้ที่ 70%
  • Parallel Hint Optimization: ทดสอบถอด PARALLEL Hint ออก หรือปรับ SQL ให้เหมาะสมกับ 2 CPU ที่มีอยู่ หากจำเป็นต้องใช้ Parallel จริงๆ ควรพิจารณาเพิ่ม CPU หรือเปลี่ยนเป็น RAC หลังจากบำรุงรักษาระบบเรียบร้อยแล้วเท่านั้น
  • Proactive Maintenance: ดูแลระบบอย่างสม่ำเสมอโดย DBA จะช่วยลดระยะเวลาการทำงานของ Automated Job ได้อย่างมาก
📊
เนื้อหาพิเศษ: เทคนิคจากที่ปรึกษา
🔬 การอ่านกราฟ CPU and Wait Time Tuning Dimensions

ในการวิเคราะห์เชิงลึก เราใช้สมการ: DB time = DB CPU time + DB wait time เพื่อพล็อตพิกัดบนกราฟ และเลือกกลยุทธ์การแก้ไขได้อย่างแม่นยำ:

CPU and Wait Time Tuning Dimensions — Oracle AWR Analysis Chart
Gray Zone
Possibly Needs SQL Tuning
CPU สูง, Wait ต่ำ — Application สั่ง Query หนัก CPU จนเกินไป ควรจูน SQL เป็นหลัก
Blue Zone
Scalable Application
Loader Process (CPU 46.64%, Wait 53.36%) — อยู่โซนนี้ การเพิ่ม CPU หรือ RAC Node จะช่วยได้โดยตรง
Red Zone
Needs Instance/RAC Tuning
Rating & Summary Process (Wait >74–75%) — อยู่โซนนี้ เพิ่ม CPU ไม่ช่วย ต้องทำ Instance Tuning เสียก่อน
💡

การประเมินระบบผ่านกราฟ — มาตรฐานการทำงานของ VT Technology

การประเมินสถานะผ่านกราฟนี้ช่วยให้ลูกค้าแก้ปัญหา Database ได้ตรงจุด ลดความสูญเสียจาก Downtime และประหยัดงบประมาณการขยายฮาร์ดแวร์ที่ไม่จำเป็นได้อย่างมีประสิทธิภาพ

บทนำ: ตาราง Transaction เดียว สะสมข้อมูลเกินหลายปีโดยไม่เคย Purge

ระบบฉากหลักของผู้ให้บริการ Digital Content บนมือถือ (ระบบ API Gateway ที่รับส่งการชำระเงินและ Content Delivery) เกิดอาการช้าลงเรื่อยๆ จากการวิเคราะห์ AWR Report ทีมพบว่าตัวการ Logical Reads สูงถึง 707 ล้าน Block ต่อ session เพียง 6 ชั่วโมง

🚨
The Challenge — AWR ชี้จุดปัญหา
📊 Logical Reads 707 ล้าน Block/6hr — ตารางเดียวถูกอ่านซ้ำเสมอแบบ Full Scan

AWR Snapshot ช่วง 6 ชั่วโมง ระบบใช้ CPU ไป 23.91% แต่ SQL Elapsed Time ไปถึง 78.21% ของ DB Time ทั้งหมด จากการวิเคราะห์ Segment พบว่า:

  • PN_DISTRIBUTION_CONTENT (88.92%): ตารางเดียวกิน Logical Reads ไปถึง 628 ล้าน Block (จาก 707 ล้านทั้งหมด) เป็นตาราง Reference จำนวนมากแต่ไม่เคยมี Index
  • PN_KIKU_API_DB (5.47%): ตาราง Transaction หลัก มีข้อมูลสะสมตั้งแต่ปี 2013 โดยไม่เคยลบส่วนเก่าออก Index ที่มีอยู่ยังเป็นแบบ Global ทำให้ Partition Pruning ไม่เกิดขึ้น
🔍
Root Cause Analysis — 2 ตัวงานหลัก
📂 ไม่มี Partition Index + ข้อมูลเก่าสะสมไม่เคยลบ

ทีมตรวจสอบโครงสร้างตารางและ Index แล้วพบปัญหา 2 จุด:

Design
Global Index บน Partition Table
ตาราง Transaction (PN_KIKU_API_DB) ใช้ Partition by DATE แต่ Index ถูกสร้างเป็นแบบ Global ทำให้ Query ต้อง Full Scan ทุก Partition แทนที่จะดูเฉพาะ Partition ที่เกี่ยวข้อง
Data Volume
ข้อมูลสะสม 3+ ปีไม่เคยลบ
ข้อมูล Transaction ตั้งแต่ปี 2013 ยังคงอยู่ในตารางเดียวกันกับข้อมูลปัจจุบัน ทำให้ปริมาณข้อมูลที่ต้องสแกน Full Scan นั้นใหญ่ขึ้นเรื่อยๆ
No Archiving
ไม่มีกลยุทธ์ Data Lifecycle
ไม่มี Policy การย้ายข้อมูลเก่าออกหรือ Drop Partition ทำให้ตารางต้องทำงานกับปริมาณที่มากขึ้นเรื่อยๆ ตลอดเวลา
🛠️
The Solution — 3 แนวทางที่ดำเนินการ
⚡ Partition Index + Database Link + Automated Archiving
  • Step 1 — เปลี่ยน Global Index เป็น Local Partition Index: สร้าง Index ใหม่สำหรับตาราง Transaction โดยเพิ่ม keyword LOCAL ท้ายคำสั่ง CREATE INDEX ทำให้ Oracle Optimizer เลือกอ่านเฉพาะ Partition ที่ตรงกับ Condition ได้ (Partition Pruning) ลด Logical Reads ได้อย่างมหาศาล
  • Step 2 — ย้ายข้อมูลผ่าน Database Link: สร้าง Procedure ย้ายข้อมูลเก่า (มากกว่า 3 ปี) ออกไปเก็บไว้ในเครื่องสำรองแยกต่างหาก (ผ่าน Database Link) หรือ Export เป็น Dump file สำรองไว้ก่อนลบ
  • Step 3 — Drop Partition ข้อมูลเก่า: ใช้คำสั่ง ALTER TABLE ... DROP PARTITION ลบข้อมูลตั้งแต่ปี 2015 ออกจากตารางหลัก สามารถทำได้แบบ Online โดยไม่ต้องหยุดระบบ
  • Step 4 — ตั้ง Automated Archiving Job: สร้าง Scheduler Job (DBMS_SCHEDULER) ให้ย้ายข้อมูลเก่าออกอัตโนมัติทุกวันเวลา 01:00 น. เพื่อรักษาขนาดตารางให้อยู่ในระดับที่เหมาะสมตลอดไป
💡
บทสรุปทางเทคนิค
Local Partition Index คือหัวใจของการจูน Partition Table
💡

Partition Table โดยไม่มี Local Index เทียบกับไม่ได้ Partition เลย

สิ่งที่สำคัญที่สุดของการออกแบบ Partition Table คือการให้ Index เป็นแบบ LOCAL เสมอ เพื่อให้ Oracle สามารถทำ Partition Pruning อ่านเฉพาะ Partition ที่จำเป็นได้ แทนที่จะสแกนทุก Partition นอกจากนี้ การวางแผน Data Lifecycle Management ที่ดี ด้วยการ Archive และ Drop Partition อย่างสม่ำเสมอ จะช่วยรักษาประสิทธิภาพให้ระบบยืนยาวได้อย่างยั่งยืน

บทนำ: เครื่อง 64 CPU แต่ตั้งค่า Memory ไว้เพียง 32MB

ระบบงานหลักของหน่วยงานด้านการบินใช้ Oracle 9i Enterprise Edition บนเครื่องเซิร์ฟเวอร์ 64-bit ที่มี CPU ถึง 64 Core แต่ค่า pga_aggregate_target ถูกตั้งไว้เพียง 32MB และ Buffer Cache เพียง 144MB จาก SGA Max 462MB — เทียบไม่ได้สัดส่วนกับขนาดของเครื่องเลย

🚨
The Challenge — อาการของระบบ
💻 Physical Reads สูงผิดปกติ — ระบบไปดึงข้อมูลจาก Disk แทน Cache ตลอดเวลา

ระบบเกิดอาการ I/O สูงผิดปกติ Query ทำงานช้าลง จากการวิเคราะห์ผ่าน v$db_cache_advice พบว่าที่ Buffer Cache ปัจจุบัน 144MB นั้น Physical Read Factor สูงถึง 24.7× เมื่อเทียบกับขนาดที่เหมาะสม (ที่ 96-112MB ก็ลดลงเหลือ 3.5× และ 1.5× ตามลำดับ)

🔍
Root Cause Analysis — Memory Advisor ชี้จุด
📊 Buffer Cache และ PGA ถูกตั้งค่าต่ำเกินไปมากสำหรับระบบ Oracle 9i

ทีมรัน Memory Advisor ของ Oracle (ผ่าน v$db_cache_advice และ v$pga_target_advice) และพบปัญหาชัดเจน 2 จุด:

Buffer Cache
144MB เล็กเกินไป — Physical Read สูง 24.7×
db_cache_size = 144MB ทำให้ Oracle ต้องอ่าน Disk บ่อยมาก Buffer Cache Advice ชี้ว่าถ้าเพิ่มเป็น 96-112MB จะลด Physical Read ได้ถึง 3-7× (แต่ตั้งไว้น้อยเกินไป)
PGA Target
32MB สำหรับ 64-CPU Server
pga_aggregate_target = 32MB เล็กเกินไปมาก ทำให้ Sort/Hash Join ต้อง Spill ลง Temp Disk บ่อย เกิดเป็น One-pass/Multipass executions แทน Optimal
SGA Imbalance
SGA 462MB แต่จัดสรรขาดผิดสัดส่วน
SGA ใช้ java_pool 112MB และ shared_pool 112MB แต่ buffer_cache เพียง 144MB — ไม่สอดคล้องกับบารมี ควรจัดสรร Buffer Cache ให้มากกว่านี้
🛠️
The Solution — ใช้ Memory Advisor นำทาง
⚡ ปรับค่า Buffer Cache และ PGA ตามคำแนะนำของ Oracle Advisor
  • Step 1 — สำรวจ Buffer Cache Advice (v$db_cache_advice): พิจารณา ESTD_PHYSICAL_READ_FACTOR ที่ขนาด 96-112MB ลดลงเหลือ 3.5× จาก 144MB (ขนาดปัจจุบัน) — เป็นจุด Sweet Spot ที่คุ้มค่าที่สุด
  • Step 2 — ปรับ pga_aggregate_target: เพิ่มค่าจาก 32MB เป็นค่าที่เหมาะสมกับขนาดเครื่อง (Oracle แนะนำให้ใช้ 20% ของ Physical Memory หรือตามค่า ESTD_OPTIMAL_EXECUTIONS จาก v$pga_target_advice)
  • Step 3 — จัด SGA ใหม่: ลด java_pool_size จาก 112MB ลง (ระบบไม่ใช้ Java) และนำพื้นที่ไปเพิ่ม Buffer Cache ให้อยู่ในช่วง 200-250MB เพื่อประสิทธิภาพที่ดีที่สุดตามคำแนะนำของ Advisor
💡
บทสรุปทางเทคนิค
Oracle Memory Advisor — เครื่องมือฟรีที่ช่วยตัดสินใจเรื่อง Memory ได้อย่างแม่นยำ
💡

ไม่จำเป็นเดาสุ่ม — เปิด Advisor แล้ววิเคราะห์ก่อนปรับค่า

Oracle มีเครื่องมือ Memory Advisor ติดตั้งมาให้ฟรี (v$db_cache_advice, v$pga_target_advice, v$shared_pool_advice) ก่อนปรับค่าใดๆ ควรวิเคราะห์ข้อมูลจาก Advisor เหล่านี้เสมอเพื่อให้แน่ใจว่าการเพิ่มค่า Memory จะช่วยเรื่องคุ้มค่าจริง ไม่ใช่การเดาสุ่มแบบไร้ทิศทาง

บทนำ: AWR Compare Period เผยข้อมูลเปรียบเทียบ 2 ช่วงเวลา ชี้ตนตอปัญหาได้ชัดเจน

ระบบ CRM ขององค์กรขนาดใหญ่เกิดความช้าลงอย่างมีนัยสำคัญ ครั้งนี้ใช้เครื่องมือทั้ง AWR Report และ AWR Compare Period เปรียบเทียบช่วงเวลาปกติ (12 Feb) กับช่วงที่ยุ่ง (13 Feb) เพื่อไล่เรียงต้นตอปัญหาอย่างแม่นยำ

🚨
The Challenge — Compare Period ชี้ความต่าง
📊 Top 5 Events เปลี่ยนไปโดยสิ้นเชิง ระหว่างช่วงปกติกับช่วงยุ่ง

จาก AWR Compare Period เปรียบช่วงปกติ (12 ก.พ.) กับช่วงยุ่ง (13 ก.พ.) พบความแตกต่างชัดเจน:

Eventช่วงปกติ (%)ช่วงยุ่ง (%)
CPU time72.60%27.02% ↓
enq: TM - contention61.98% ↑↑↑
log file sync17.48%5.71%
log file parallel write10.55%3.50%

ตัวร้ายหลัก: ในช่วงปกติ CPU ใช้ 72% (สูงสุด) แต่ช่วงยุ่ง CPU เหลือแค่ 27% เพราะ enq: TM contention ดูดเวลาไปถึง 62% แสดงว่า Session ตัวหนึ่งกำลังล็อก Table อยู่ ทำให้ Session อื่นๆ ทำงานไม่ได้

🔍
Root Cause Analysis — 2 ปัญหาซ้อนทับกัน
🔐 Table Lock + Redo Log I/O เป็นตัวถ่วงประสิทธิภาพ
enq: TM
Table-level Lock Contention — Session กำลังติดกันอยู่
Wait Event enq: TM - contention คือสัญญาณว่ามี Session หนึ่งทำ DML บน Table ที่ไม่มี Foreign Key Index ทำให้ Oracle ต้อง Lock ทั้ง Table แทนที่จะ Lock แค่บาง Row อย่างที่ควรจะเป็น
log file sync
Redo Log I/O ช้า — Commit ต้องรอให้ Redo เขียนลง Disk
Redo Size สูง 67,926 Bytes/sec และ log file sync avg wait 26ms/Commit เพราะ Redo Log File อาจเล็กเกินไปหรือ disk I/O ช้า ทำให้ Commit ปล่อย Session ช้า
🛠️
The Solution — แก้ 2 จุดคนละ
⚡ สร้าง FK Index + โยกย้าย Redo Log ไปดิสก์ที่เร็วขึ้น
  • แก้ปัญหา TM Contention — สร้าง Index บน Foreign Key: ใน Oracle ถ้า Child Table ไม่มี Index บน Foreign Key Column Oracle จะต้อง Lock ทั้ง Table เมื่อ Parent Row ถูกแก้ไข วิธีแก้ไขคือสร้าง CREATE INDEX บน FK Column ใน Child Table ทุกตารางที่เกี่ยวข้อง
  • แก้ปัญหา log file sync — ปรับ Redo Log: ตรวจสอบขนาด Redo Log File (ควรใหญ่กว่าปริมาณ Redo ใน 15-20 นาที) และชักนำ Redo Log Files ไปไว้บน Disk / Volume ที่เร็วโดยเฉพาะ หรือพิจารณาใช้ COMMIT_WAIT และ COMMIT_LOGGING (ถ้า consistency ยอมรับได้)
  • ใช้ AWR Compare Period เป็นเครื่องมือยืนยันผล: หลังปรับค่าแล้ว ใช้เครื่องมือ Compare Period เปรียบเทียบช่วงก่อน-หลังแก้ไข เพื่อยืนยันว่าปรับได้ผลจริงและไม่เกิด Regression ใด
💡
บทสรุปทางเทคนิค
Foreign Key ไม่มี Index คือจุดบอดพร้อมเสมอในระบบ Oracle
💡

TM Contention มักซ่อนอยู่ สาเหตุหลัก: Foreign Key ไม่มี Index

ใน Oracle ถ้า Child Table ปราศจาก Foreign Key Column หาก DML ใน Parent Table เกิดขึ้น Oracle จะ Lock Table-level บน Child Table ทั้งหมด แทนที่จะ Row-level lock เพียงบาง Row ทำให้ทุก Session ที่พยายแตะ Child Table ต้อง Wait การแก้ไขง่ายด้วยการสร้าง CREATE INDEX ... ON child_table(fk_column) จะช่วยลด TM Contention ได้อย่างมาก

บทนำ: RAC 2-Node แต่แต่ละ Node มีปัญหาคนละชุด

ระบบหลักของบริษัทด้านโลจิสติกส์/เดินเรือใช้ Oracle RAC 2-Node เพื่อ High Availability แต่ระบบเพิ่มความช้าลงอย่างต่อเนื่อง จากการวิเคราะห์ AWR ทั้ง 2 Instance พบว่าแต่ละ Node มีปัญหาคนละชุด ทำให้ระบบช้าลงมากกว่าที่ควร

🚨
The Challenge — AWR 2 Instance เผยปัญหาคนละ Node
📊 Node 1: Streams Capture ค้าง Archive & Node 2: Backup I/O แย่ง Disk

เปรียบ AWR ทั้ง 2 Instance ในช่วงเดียวกัน พบปัญหาคนละชุด:

EventNode 1 (%)Node 2 (%)
CPU time28.5%37.4%
db file sequential read17.0%16.4%
Streams capture: waiting for archive log6.4%
Backup: sbtwrite26.1%
gc cr block busy / gc current block1.4%2.6%

ปัญหาทั้ง 2 Node เกิดปัญหาด้าน I/O ต่างไม่เกี่ยวกัน — Node 1 จาก Streams Process ค้างบน Archive Log ในช่วงที่ระบบผลิต และ Node 2 จาก Backup กำลังวิ่งแย่งกับ I/O สำหรับ Workload ปกติ

🔍
Root Cause Analysis — เจาะลึกราย Node
🔄 Streams + Backup ทำงานชนกับ Production Workload
Node 1
Streams Capture ค้าง Archive Log ในช่วงเวลา Production
Streams Capture Process ทำหน้าที่อ่าน Redo Log เพื่อรับข้อมูลในการทำ Replication แต่ Archive Log ไม่มีมากพอทำให้ Capture Process ต้องรออยู่ (Streams capture: waiting for archive log) กินไปถึง 6.4% ของ DB Time ที่ควรไปทำงาน Production
Node 2
Backup วิ่งตรงช่วง Peak Hour — I/O แย่งกัน Workload ปกติ
Backup: sbtwrite2 คือการ Write ไปยัง Tape/SBT Library ใช้ I/O ถึง 6.1% ของ DB Time คอนกับการอ่าน io done 5.8% ปัญหาคือ Backup Job ใช้ I/O ชนกับงาน Production
Both Nodes
gc block events — RAC Interconnect Traffic
Wait Events gc cr block busy และ gc current block 2-way พบทั้ง 2 Node สะท้อนว่ามี Data ถูกรับส่งผ่าน Interconnect สูง Interconnect Traffic 10,513 KB/s บ่งชี้ว่า Hot Block ถูก Access ผิดปกติ
🛠️
The Solution — แยกงานออกจากนั้น อย่าให้ชน Production Workload
⚡ จัด Schedule + เพิ่ม Archive Retention + แยก I/O Path
  • Node 1 — ปรับ Streams Capture: เพิ่มจำนวน Archive Log (หรือเส้น LOG_ARCHIVE_DEST ให้เพียงพอ สำหรับ Streams Capture) เพื่อไม่ให้ Capture Process ต้องรอ Archive Log ที่ถูก Delete ไปก่อนกำหนด หรือสร้าง Standby ที่ Capture เร็วขึ้น
  • Node 2 — ย้าย Backup ออกนอกช่วง Production: เลื่อน Backup Job ไปทำในช่วง Off-Peak (เช่น ตี 1-5 น.) เพื่อไม่แย่ง I/O กับงาน Production หรือใช้การควบคุม I/O Priority เพื่อให้ Backup กระทบน้อยที่สุด
  • Both Nodes — ตรวจสอบ Hot Block: วิเคราะห์ gc block events ด้วย ASH (Active Session History) เพื่อหาว่า Block/Segment ไหนถูก Access จากหลาย Session พร้อมกัน และพิจารณาใช้ Sequence Caching หรือ Row Ordering ลด Interconnect Contention
💡
บทสรุปทางเทคนิค
RAC ต้องวิเคราะห์ ทุก Node แยกกัน — ปัญหาอาจไม่เหมือนกัน
💡

การ Tune RAC ต้องดู AWR ทุก Instance — ไม่ใช่แค่ Instance เดียว

ในระบบ RAC ปัญหามักพบว่า แต่ละ Node มีตัวร้ายคนละชุด การดูแค่ AWR ของ Node หลักอย่างเดียวอาจพลาดปัญหาสำคัญได้ โดยเฉพาะ Streams/Replication ควรจัดประเภท Node ให้ชัดเจน และ Backup Job ควรแยกวิ่งในช่วง Off-Peak เสมอ

บทนำ: AWR ชี้ว่าตาราง System กิน Physical Read มากกว่า Business Table

ระบบชำระเงินแห่งหนึ่งใช้ Oracle 11g บน HP-UX 64-bit เกิดอาการช้าลงโดยไม่มีสาเหตุชัดเจน จาก Segment Stats ใน AWR พบว่าตาราง AUD$ (Oracle Audit Trail) ที่ไม่ใช่ Business Table เลย กลับกิน Physical Read ไปถึง 33.72% ของทั้งหมด

🚨
The Challenge — Segment Stats เผยผู้ร้ายที่ไม่คาดคิด
📊 AUD$ กิน Physical Read 33% — สูงกว่าตาราง Business หลัก

จาก AWR Report ช่วงเช้า (4 ชั่วโมง) พบว่า Physical Reads สูง 1,516 ครั้ง/วินาที เมื่อเจาะ Segment Stats พบว่า:

ตารางPhysical Reads%Total
SYS.AUD$ (SYSAUX)7,373,36233.72%
CATPOS.RECEIPT7,104,51032.49%
CATPOS.ACCOUNT5,502,90225.17%
CATPOS.CONTRACT1,397,0226.39%

AUD$ สูงกว่า Business Table หลัก! นั่นหมายความว่าการตรวจสอบสิทธิ์ (DB Audit) ทำให้เกิดงาน I/O สูงแบบไม่คาดคิด

🔍
Root Cause Analysis
📢 DB Audit เปิดที้ไว้ + AUD$ ไม่เคย Purge พอกกันจนขนาดเดียวกับตาราง Business
DB Audit ON
เปิด Auditing ทุก Operation
ระบบเปิด DB Audit โดยไม่จำกัด Scope ทำให้ Oracle เขียนบันทึกทุกการกระทำที่ตรวจสอบลงใน AUD$ เรื่อยๆ งาน Insert แต่ละครั้งต้อง Physical Read/Write ผ่าน AUD$ ด้วย
No Purge
AUD$ สะสมจนใหญ่มาก ไม่เคยลบออก
ไม่มีการ Purge / Truncate AUD$ เลย ทำให้ตารางที่อยู่ใน SYSAUX ขนาดใหญ่ขึ้นเรื่อยๆ จน Full Table Scan ใช้เวลานานขึ้นทุกครั้งที่มี Audit
SYSAUX Pressure
SYSAUX ถูกกดดันจาก AUD$
AUD$ อยู่ใน SYSAUX Tablespace ที่ยังรวม AWR, ADDM และเครื่องมือต่างๆ AUD$ แสดงว่าไม่ได้ถูกเคลียส์เลย
🛠️
The Solution — 3 ขั้นตอน
⚡ Purge AUD$ + จำกัด Scope + ย้ายไป Tablespace แยก
  • Step 1 — Purge AUD$ ทันที: บันทึกข้อมูลเก่าออกไป จากนั้น Truncate หรือใช้ DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL ลบบันทึกเก่าออกอย่างสม่ำเสมอ (Scheduled Purge)
  • Step 2 — จำกัด Audit Scope: ตรวจสอบว่าต้อง Audit อะไรบ้าง ใช้ NOAUDIT สำหรับ Operation ที่ไม่จำเป็นต้องตรวจสอบ หรือเปลี่ยนไปเขียน Audit ลง OS File (AUDIT_TRAIL=OS) แทนตาราง
  • Step 3 — ย้าย AUD$ ออกจาก SYSAUX: ใช้ DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_LOCATION ย้าย AUD$ ไปไว้ประเภท Tablespace แยกต่างหาก (Oracle 11g+) เพื่อไม่กระทบ SYSAUX
💡
บทสรุปทางเทคนิค
สัญญาณเตือน: ถ้า SYSAUX Tables ติดอันดับต้น Hot Segment — ตรวจสอบ DB Audit ทันที
💡

AUD$ คือจุดบอดที่หลาย DBA มักมองข้าม

เมื่อ AWR ชี้ว่า SYSAUX ติดอันดับ Hot Segment สิ่งแรกที่ควรตรวจสอบคือ AUD$ การเปิด DB Audit โดยไม่ระบุ Scope และไม่มีการ Purge อย่างสม่ำเสมอ สามารถทำให้ระบบช้าแบบสืบหาสาเหตุไม่ได้เลย

บทนำ: Redo 269,000 Bytes/วินาที แต่ Redo Log ไม่ได้รับการปรับจูน

ระบบ Radius Authentication สำหรับ Internet Service Provider (ISP) ใช้ Oracle RAC 2-Node ช่วง Peak พบว่าระบบช้าลงอย่างรุนแรง AWR ชี้ว่า Redo size สูงถึง 269,681 Bytes/วินาที และ log file sync ใช้เวลา 38.3% ของ DB Time ทั้งหมด

🚨
The Challenge — Top 5 Events
📊 log file sync 38% + Backup I/O 30% — งาน I/O ถูกดูดไปหมด
Event% DB TimeAvg Wait
log file sync38.3%10 ms
CPU time24.8%
Backup: sbtbackup17.3%219,092 ms (!)
Backup: sbtwrite212.9%4 ms
gc current block 2-way12.2%1 ms

น่าตกใจที่สุด: Backup sbtbackup มี Avg Wait สูงถึง 219 วินาทีต่อครั้ง เลย แสดงว่า Tape/SBT ตอบสนองช้ามาก

🔍
Root Cause Analysis
🔁 Commit บ่อยเกินไป + Redo Log ไม่เพียงพอ
High Redo
Redo Size 269KB/s — Commit แต่ละ User Request
ระบบ Radius ต้อง Commit ทุกครั้งที่มี User Login/Logout เกิดแบบ OLTP Transaction ในปริมาณสูงมาก Redo สูง 269,681 Bytes/วินาที ทำให้ LGWR ต้อง Flush บ่อยมาก
Redo Log Size
ขนาด Redo Log File เล็กเกินไป
Redo Log Switch เกิดบ่อยเกินไป (Log Checkpoint) ทำให้เกิด I/O เพิ่มเติม แต่ละ Commit ยิ่งต้องรอให้ LGWR เพียงพอก่อน (log file sync)
Backup Timing
Backup วิ่งช่วง Peak — Tape Wait 219 วินาที/ครั้ง
Backup sbtbackup (Tape Library) มี Avg Wait 219,092ms แสดงว่า Tape เตรียมสายช้ามาก การ Backup จึงชนกับ I/O ที่ระบบต้องใช้อยู่แล้ว
🛠️
The Solution
⚡ ขยาย Redo Log + ช้า Commit + ย้าย Backup ออก Off-Peak
  • Step 1 — เพิ่มขนาด Redo Log File: คำนวณจาก Redo Size (269K/s) ควรปรับเป็น Redo Log ที่ใหญ่พอกับปริมาณ Redo ใน 15-20 นาที เพื่อลด Log Switch และลดความถี่ของ LGWR
  • Step 2 — พิจารณา Batch Commit: สำหรับระบบ OLTP ที่ Commit ทุก row พิจารณาปรับแอปพลิเคชันให้ Commit เป็นชุด (Batch) เพื่อลด Redo flush ต่อครั้ง หรือใช้ COMMIT_WRITE แบบ Asynchronous
  • Step 3 — ย้าย Backup ออก Off-Peak: Tape Avg Wait 219 วินาทีคืออันตรายเกินไป เลื่อน Backup Job ออกสู่ช่วง Off-Peak หรือใช้ Disk Staging แทน Tape โดยตรง และค่อยโอนไป Tape ภายหลัง
💡
บทสรุปทางเทคนิค
log file sync สูง = Commit มาก + Redo Log เล็ก เสมอ
💡

log file sync คือสัญญาณที่ LGWR ต้องทำงานหนักเกินไป

เมื่อ log file sync สูงให้ตรวจสอบ 3 สิ่งพร้อมกัน: (1) Redo size สูงเกินไป ควรปรับ Redo Log ให้ใหญ่ขึ้น (2) Disk I/O ช้า ย้าย Redo Log ไป Disk ที่เร็วขึ้น (3) Commit บ่อยเกินไป ปรับ Application ให้ Batch Commit

💾 กู้คืนระบบล่ม (Disaster Recovery) 3

บทนำ: ระบบงานสำคัญของรัฐหยุดกะทันหัน ไม่ใช่เพราะฮาร์ดแวร์พัง

เมื่อระบบของหน่วยงานราชการล่ม ทุกวินาทีมีความหมาย นี่คือเหตุการณ์ Incident Support ฉุกเฉินที่ทีมที่ปรึกษาได้รับสายด่วน เพราะระบบงานหลักทั้งหมดไม่สามารถบันทึกข้อมูลใหม่ได้ ทั้งที่เซิร์ฟเวอร์ยังทำงานอยู่ปกติ

🚨
The Incident — รับแจ้งเหตุฉุกเฉิน
🏛️ ระบบงานตุลาการหยุดชะงัก บันทึกข้อมูลไม่ได้ทั้งระบบ

ทาง Vendor ผู้ดูแลระบบให้กับหน่วยงานด้านตุลาการ ติดต่อขอความช่วยเหลือด่วน เนื่องจากแอปพลิเคชันระบบงานหลักเกิดการหยุดชะงัก ไม่สามารถบันทึกทรานแซกชันใหม่ลงในฐานข้อมูลได้เลย ส่งผลให้การปฏิบัติงานของเจ้าหน้าที่สะดุดลงอย่างสิ้นเชิง

🔍
Root Cause Analysis — เจาะหาต้นตอ
📦 ปัญหาไม่ได้อยู่ที่ฮาร์ดแวร์ แต่อยู่ที่ Storage Architecture

ทีมที่ปรึกษา Remote เข้าสู่ระบบ Linux เพื่อตรวจสอบ Oracle Database Log ทันที พบว่าสาเหตุไม่ใช่ Hardware หรือ Network แต่เป็นปัญหาโครงสร้างการจัดเก็บข้อมูลที่สะสมมานาน:

Design
กระจุกตัวใน Tablespace เดียว
Table ทำงานทั้งหมดถูกรวมไว้ใน Tablespace เดียวกัน ไม่มีการแยกตามกลุ่มข้อมูล
Structure
Single Datafile (Smallfile)
Tablespace ผูกกับ Datafile ไฟล์เดียว แบบ Smallfile Tablespace ไม่มีการ Add Datafile เพิ่ม
Limit Hit
เพดาน 32 GB (8KB Block)
Block Size 8KB กำหนดเพดาน Datafile สูงสุด ~32 GB เมื่อเต็ม Auto-extend ไม่สามารถทำงานได้อีก เกิด ORA-01653
🛠️
The Solution — กู้ระบบแบบ Zero Downtime
⚡ Add Datafile ออนไลน์ — ระบบกลับมาในเวลาอันรวดเร็ว

เพื่อให้ระบบกลับมาให้บริการได้เร็วที่สุด ทีมงานดำเนินการแก้ไขปัญหาเฉพาะหน้าอย่างเร่งด่วน:

  • Add Datafile ไฟล์ใหม่เข้า Tablespace เดิม: ใช้คำสั่ง ALTER TABLESPACE ... ADD DATAFILE เพิ่ม Datafile ใหม่เข้าไปใน Tablespace ที่เต็มอยู่ เปิดพื้นที่จัดเก็บใหม่ให้ระบบทำงานต่อได้ทันที
  • Online Operation — Zero Downtime: กระบวนการทั้งหมดสามารถทำได้แบบ Online โดยไม่ต้องหยุด Database แม้แต่วินาทีเดียว ทำให้ระบบกลับมาบันทึกข้อมูลได้อย่างรวดเร็วโดยไม่กระทบการให้บริการ
💡
Recommendations — ป้องกันไม่ให้เกิดซ้ำ
ข้อเสนอแนะเชิงสถาปัตยกรรมสำหรับ Vendor
💡

2 มาตรการป้องกันที่ต้องทำก่อนประวัติศาสตร์ซ้ำรอย

1. Database Monitoring & Alert: ตั้งค่าแจ้งเตือนเมื่อ Datafile / Tablespace ถูกใช้งานถึง 80–90% เพื่อเพิ่มพื้นที่ได้ล่วงหน้า ก่อนจะถึงเพดาน
2. Tablespace Segregation: แยก Tablespace ตามกลุ่มข้อมูล หรือแยก Data / Index อย่างชัดเจน ลดความเสี่ยงที่ข้อมูลกลุ่มหนึ่งจะกระทบทั้งระบบ และง่ายต่อการบริหารจัดการ I/O

บทนำ: เมื่อสายป้องกันภัยขาดช่วงเพราะไฟล์หาย

ระบบ DR ที่ดูเหมือนทำงานปกติอาจซ่อนความเสี่ยงไว้โดยไม่รู้ตัว เพราะข้อมูลบนเครื่อง DR ไม่ได้อัปเดตตามเครื่องหลักอยู่เรื่อยๆ หากต้องสลับมาใช้ DR จริงๆ ข้อมูลที่บันทึกใหม่หลายชั่วโมงหรือหลายวันจะหายไป

🚨
The Incident — สัญญาณเตือนปรากฏขึ้น
🔄 DC และ DR หยุด Sync กันแล้ว โดยไม่รู้สาเหตุ

ระบบแจ้งเตือนรายงานว่าสถานะของฐานข้อมูลระหว่าง DC และ DR Site ไม่ทำการ Sync ถึงกันเป็นระยะเวลาหนึ่ง ข้อมูลบนเครื่อง DR ไม่อัปเดตตามเครื่องหลัก ทำให้เกิดความเสี่ยงสูงหากต้องสลับไปใช้งาน DR Site จริง

🔍
Root Cause Analysis — สืบสวน Log
📂 Archive Log สูญหายระหว่างทาง — Standby จึงไล่ตามไม่ทัน

ทีมที่ปรึกษาตรวจสอบ Log file และสถานะ Standby Database แล้วพบสาเหตุชัดเจน:

  • Log Sequence ขาดตอน: มีไฟล์ Archive Log บางส่วนสูญหายไประหว่างทาง (Missing Archive Log) ทำให้ Sequence ต่อเนื่องยังไม่ครบ
  • การทำงานของ Standby: ระบบต้องอ่าน Archive Log ตามลำดับ Sequence อย่างต่อเนื่อง เมื่อไฟล์ใดไฟล์หนึ่งแหว่งหาย กระบวนการ Apply Log บนเครื่อง DR จะหยุดชะงักทันที ไม่สามารถข้ามไปอ่านไฟล์ลำดับถัดไปได้
  • สาเหตุของการสูญหาย: อาจเกิดจาก Network สะดุดชั่วคราว, พื้นที่จัดเก็บเต็มแล้วระบบ Auto-delete ลบไฟล์ทิ้งก่อนส่ง, หรือความผิดพลาดระดับ OS — เมื่อไฟล์ถูกลบออกจากเครื่อง DC แล้ว DR จึงไม่สามารถไล่ตามได้อีกต่อไป
🛠️
The Solution — Rebuild DR Site ใหม่ทั้งหมด
⚡ Re-instantiate DR ด้วย Database Cloning จาก DC

เนื่องจากไฟล์ Archive Log ที่หายไปไม่สามารถกู้คืนได้แล้ว ทีมงานดำเนินการ Rebuild DR Site ใหม่ทั้งหมด:

  • Step 1 — Stop DR Sync: หยุดโปรเซส Standby บนเครื่อง DR ชั่วคราวเพื่อเตรียมการสร้างใหม่
  • Step 2 — Database Cloning: สำรองข้อมูล (Backup) จากเครื่อง DC ในสถานะปัจจุบัน แล้วนำมาโคลน (Clone) สร้างฐานข้อมูลบนเครื่อง DR ใหม่ทั้งหมด (Re-instantiate) ให้ด้านข้อมูลตรงกับเครื่องหลัก ณ แนวเวลานั้นเป็นต้น
  • Step 3 — Re-establish Synchronization: ตั้งค่า Standby Control File ใหม่ และเปิดการทำงาน Apply Log ให้กลับมาทำงานตามปกติ
  • Step 4 — Verification: ตรวจสอบความถูกต้องของ Log Sequence ยืนยันว่าเครื่อง DR สามารถ Sync ข้อมูลตามเครื่อง DC ได้อย่างต่อเนื่องแบบ Real-time
💡
Recommendations — ป้องกันไม่ให้เกิดซ้ำ
2 มาตรการป้องกัน Archive Log สูญหายสำหรับระบบ DR
💡

ระบบ DR ที่ไว้ใจได้ต้องมีการตรวจสอบอย่างใกล้ชิด

1. ปรับ Policy การลบ Archive Log: ต้องมั่นใจว่าไฟล์จะถูกลบ ก็ต่อเมื่อถูกส่งและ Apply ลงบนเครื่อง DR เรียบร้อยแล้วเท่านั้น (เช่น RMAN DELETE ARCHIVELOG ... BACKED UP ... TO)
2. เพิ่ม Monitoring Lag Time: ติดตั้งระบบแจ้งเตือนตรวจสอบความหน่วง (Lag Time) และความสมบูรณ์ของการส่ง Archive Log อย่างใกล้ชิด เพื่อตรวจพบความผิดปกติได้ทันที ก่อนที่ไฟล์จะถูกลบทิ้งไป

บทนำ: เมื่อนโยบายความปลอดภัยกลายเป็นตัวสร้างปัญหาเอง

ระบบ Audit Log ถูกออกแบบมาเพื่อความปลอดภัย แต่เมื่อแอปพลิเคชันใช้ DDL พร่ำเพรือ ไฟล์ Audit เหล่านั้นก็สะสมจนเต็มพื้นที่โดยไม่รู้ตัว ทำให้ระบบหยุดชะงักกะทันหัน

🚨
The Incident — ระบบหยุดกะทันหัน
🏭 สายการผลิตหยุด เพราะฐานข้อมูลเขียนข้อมูลใหม่ไม่ได้

ระบบฐานข้อมูลหลักของโรงงานเกิดปัญหาขัดข้องกะทันหัน (Database Hang) ไม่สามารถประมวลผลทรานแซกชันหรือทำงานต่อได้เลย ส่งผลกระทบต่อสายการผลิตโดยตรง จากการตรวจสอบ Log เบื้องต้นพบว่าสาเหตุเกิดจาก SYSAUX Tablespace เต็มขีดจำกัด 32 GB

🔍
Root Cause Analysis — เจาะลึกใน SYSAUX
📄 Audit Log เติบโตผิดปกติ จากแอปพลิเคชันที่ใช้ DDL พร่ำเพรือ

ทีมที่ปรึกษาตรวจสอบเชิงลึกว่าทำไม SYSAUX จึงเต็มอย่างรวดเร็วผิดปกติ และพบต้นตอคือพฤติกรรมของแอปพลิเคชัน:

App Behavior
ใช้ DDL ซ้ำซากใน Loop
โปรแกรมสั่ง CREATE และ DROP TABLE ชั่วคราวซ้ำแล้วซ้ำเล่าในกระบวนการทำงาน
Audit Policy
Audit Log บันทึกทุก DDL
นโยบาย Audit ที่เปิดไว้ตาม Compliance บันทึกทุกครั้งที่แอปพลิเคชันสั่ง DDL ลงใน SYSAUX
Limit Hit
SYSAUX เต็ม 32 GB
Audit Log เติบสะสมอย่างรวดเร็ว จนถึงเพดาน Smallfile 32 GB ระบบซึ่งเขียนข้อมูลไม่ได้อีก
🛠️
The Solution — ปลดล็อกภายใต้ข้อจำกัดด้าน Compliance
⚡ Add Datafile เข้า SYSAUX แบบ Online — ระบบกลับมาทันที

ภายใต้ข้อจำกัดที่ลูกค้ายังรอ Patch จากบริษัทแม่ และไม่สามารถยกเลิก Audit Log ได้เนื่องจาก Compliance ทีมงานเลือกวิธีแก้ไขที่เหมาะสมที่สุด:

  • Add Datafile เข้า SYSAUX Tablespace: ใช้คำสั่ง ALTER TABLESPACE SYSAUX ADD DATAFILE เพิ่มไฟล์ Datafile ใหม่เข้าไปโดยตรง ขยายความจุของพื้นที่จัดเก็บโดยตรง
  • Online, Zero Downtime: การดำเนินการทำได้แบบ Online โดยไม่ต้องหยุด Database สายการผลิตกลับมาเดินหน้าได้ทันที
  • คงนโยบาย Audit Log ไว้ครบถ้วน: ระบบยังเก็บบันทึก Audit Log ตาม Compliance ได้อย่างสมบูรณ์ระหว่างรอการแก้ไขโค้ดถาวร
💡
Recommendations — ปิดความเสี่ยงระยะยาว
2 แนวทางปิดความเสี่ยง SYSAUX ระยะยาว
💡

แก้ที่ต้นเหตุของ Application คือทางออกที่ยั่งยืนที่สุด

1. Application Tuning (Global Temporary Table): ประสานงานกับบริษัทแม่เพื่อเปลี่ยนจากการใช้ CREATE/DROP TABLE พร่ำเพรือ ไปใช้ Global Temporary Table (GTT) แทน ช่วยลด Audit Log และ Redo Log ที่ไม่จำเป็นได้อย่างมหาศาล
2. Audit Log Housekeeping: ตั้งเวลา Purge ข้อมูล Audit Log ที่เก่าเกินความจำเป็นทิ้งอย่างเป็นระบบ โดยใช้แพ็กเกจ DBMS_AUDIT_MGMT คืนพื้นที่ว่างให้ระบบ และควบคุมไม่ให้ SYSAUX บวมจนควบคุมไม่ได้อีก

ระบบงานไอทีหรือฐานข้อมูลในองค์กรของคุณกำลังประสบปัญหาเหล่านี้?

ทีมงานผู้เชี่ยวชาญของ VT Technology ยินดีช่วยเหลือ ตรวจสอบ จูนนิ่งแก้ไข และวางมาตรการด้านความปลอดภัยและการสำรองข้อมูลให้องค์กรของคุณทำงานได้อย่างปลอดภัย 24x7

📝 ติดต่อวิเคราะห์ปัญหาระบบฟรี
🔧

ระบบของคุณมีปัญหาคล้ายกันไหม?

จากประสบการณ์กว่า 20 ปี ทีม VT Technology พร้อมวิเคราะห์และแก้ไขปัญหา Oracle Database ของคุณ
ทั้ง Performance Tuning, Emergency Recovery, RAC และอื่นๆ

✅ ไม่มีค่าใช้จ่ายในการปรึกษาเบื้องต้น  |  ✅ ทีมผู้เชี่ยวชาญ OCP/OCE  |  ✅ รับงานทั่วไทย

FAQ

คำถามที่พบบ่อยเกี่ยวกับ Oracle Database

คำถามและคำตอบจากประสบการณ์จริงกว่า 20 ปี ของทีม VT Technology

log file sync คือ Wait Event ที่เกิดขึ้นเมื่อ Session ทำ COMMIT แล้วต้องรอให้ LGWR (Log Writer) เขียน Redo Log Buffer ลง Disk ก่อนที่จะยืนยัน Transaction ได้ ถ้าสูงเกิน 5% ของ DB Time ให้ตรวจสอบ:

  • 📏 เพิ่มขนาด Redo Log File — ให้ใหญ่พอกับ Redo ที่เกิดใน 15-20 นาที
  • 💾 ย้าย Redo Log ไป Disk ที่เร็วกว่า — แยก Disk จาก Data File
  • 🔄 ลดความถี่ COMMIT — ปรับ Application ให้ Batch Commit แทนการ Commit ทุก Row

enq: TM - contention เกิดจากการที่ Oracle ต้อง Lock ทั้งตาราง (Table-level Lock) เมื่อมีการแก้ไข Parent Row สาเหตุหลักคือ Child Table ไม่มี Index บน Foreign Key Column ทำให้ Oracle ไม่สามารถค้นหา Child Records ได้อย่างมีประสิทธิภาพ

วิธีแก้: CREATE INDEX idx_name ON child_table(fk_column); — ใช้เวลาแค่ไม่กี่นาที แต่แก้ปัญหาได้ทันที

AWR (Automatic Workload Repository) คือรายงานสุขภาพของระบบ Oracle ที่เก็บสถิติโดยอัตโนมัติทุก 1 ชั่วโมง ประกอบด้วย:

  • 📊 Top 5 Wait Events — บอกว่าระบบ "รอ" อะไรมากที่สุด
  • 🔥 Top SQL — SQL ที่กิน CPU/I/O สูงสุด
  • 💾 Segment Statistics — ตารางหรือ Index ที่ถูก Access มากที่สุด
  • 🧠 Memory Advisor — แนะนำขนาด SGA/PGA ที่เหมาะสม

AWR เป็นจุดเริ่มต้นของการ Tune ทุกครั้ง — ทีม VT Technology ใช้ AWR เป็นพื้นฐานในทุก Consulting Case

Oracle RAC (Real Application Clusters) รัน Oracle Database บนหลายเครื่องพร้อมกัน ข้อดีคือ High Availability และ Load Balancing แต่การ Tune RAC มีความซับซ้อนกว่า เพราะต้องวิเคราะห์ AWR ทุก Node แยกกัน — ปัญหาของแต่ละ Node อาจแตกต่างกันสิ้นเชิง เช่น Node 1 มีปัญหา Streams Capture ส่วน Node 2 มีปัญหา Backup I/O ชนกับ Production Workload

ขั้นตอนเบื้องต้นที่แนะนำ:

  1. ดู AWR Report ของช่วงเวลาที่ระบบช้า — เปิดด้วย @$ORACLE_HOME/rdbms/admin/awrrpt.sql
  2. ดู Top 5 Wait Events — นี่คือสัญญาณแรกว่าปัญหาอยู่ที่ไหน
  3. วิเคราะห์ Top SQL — ดู Execution Plan ด้วย DBMS_XPLAN.DISPLAY_AWR
  4. ตรวจ Segment Statistics — ดูว่ามี System Table (เช่น AUD$) ติดอันดับ Hot Segment หรือไม่

หากต้องการความช่วยเหลือ ติดต่อทีม VT Technology ได้ทันที