ระบบช้าแบบไม่สม่ำเสมอ — และทุกคนพูดถูกทั้งนั้น
ผู้ใช้แจ้งว่าระบบ POS ตอบสนองช้าลงเป็นช่วง ๆ ไม่ใช่ช้าตลอดเวลา บางครั้งช้าประมาณ 10–15 วินาทีแล้วก็กลับมาเร็วเอง เป็นแบบนี้มาหลายเดือนแล้ว
ฝ่าย IT โทรหา Programmer ที่รับผิดชอบระบบ Programmer เปิดดู Code — "ผมไม่ได้แก้อะไรเลยนะ ทดสอบแล้วก็ผ่าน"
Programmer พูดถูก Code ไม่มีปัญหาจริง ๆ ผู้ใช้ก็พูดถูก ระบบช้าจริง ๆ แต่ไม่มีใครอธิบายได้ว่าทำไม
เข้าไปดู AWR — ตัวการไม่ใช่ Code ของ Programmer
เราดึง AWR Report ครอบคลุมช่วงเช้าที่ผู้ใช้แจ้งว่าช้า ส่วนแรกที่เปิดดูคือรายชื่อ Object ที่ถูกอ่านจาก Disk มากที่สุด
อันดับ 1 ไม่ใช่ตารางของ Application — แต่เป็น SYS.AUD$
SYS.AUD$ คือตาราง Audit Trail — แต่ Application ไม่ได้ยุ่งกับมันเลย
SYS.AUD$ เป็นตารางที่ Oracle ใช้เก็บบันทึกการ Login และการใช้งานระบบ
ไม่มีส่วนไหนของ Code Application ที่ Programmer เขียนไปยุ่งกับตารางนี้เลย
แล้วใครอ่านมัน?
เราเปิดส่วน SQL ordered by Physical Reads ใน AWR — และเจอคำตอบ:
ตัวการคือ Oracle Enterprise Manager — Monitoring Tool ที่ทีมติดตั้งไว้เพื่อดูแลระบบ ไม่ใช่ Application ของ Programmer แต่อย่างใด
เช็ค Failed Login ทุก 30 นาที แต่วิธีที่ใช้ทำให้ต้องอ่าน Disk ทั้งตาราง
เราเปิด SQL Text จริงของ OEM จาก AWR:
ดูเหมือน Query ธรรมดา แต่ปัญหาอยู่ที่ TO_CHAR(timestamp, ...)
ในบรรทัด WHERE — การครอบ Column ด้วย Function ทำให้ Oracle ไม่สามารถใช้ Index ได้
จึงต้องไล่อ่าน ทุก Row ในตาราง เพื่อหาข้อมูล 30 นาทีที่ต้องการ
ปัญหานี้มีอยู่ตั้งแต่วันแรก — แค่ยังเล็กเกินกว่าจะรู้สึก
ตอนที่ติดตั้งระบบครั้งแรก SYS.AUD$ ยังเล็กอยู่
OEM วิ่ง Query เดิมนี้ทุก 30 นาทีเหมือนกัน แต่ตารางเล็ก ไล่อ่านไวมาก
ใช้เวลาไม่ถึงวินาที ไม่มีใครรู้สึก
แก้ได้โดยไม่ต้องแตะ Code ของ Programmer เลยแม้แต่บรรทัดเดียว
Function-Based Index — ทำให้ OEM หาข้อมูลได้โดยไม่ต้องอ่านทั้งตาราง
เนื่องจาก OEM ใช้ TO_CHAR(timestamp, ...) ในการถาม
เราสร้าง Index ที่ตรงกับ Expression นั้นพอดี
ทำให้ OEM สามารถ Seek ตรงไปยังข้อมูล 30 นาทีที่ต้องการได้เลย
ไม่ต้องอ่านทั้งตารางอีกต่อไป
ตารางเล็กลง ปัญหาเดิมก็ไม่กลับมา
เราตั้ง DBMS_AUDIT_MGMT ให้ล้าง Audit Record ที่เก่าเกินกำหนดออกเป็นรอบ
โดย Archive ไว้ก่อนตามข้อกำหนดขององค์กร
เพื่อให้ตารางไม่โตจนหนักอีกในอนาคต
SYS.AUD$ หายไปจาก AWR Report แทบทันที
ผู้ใช้ไม่รู้สึกว่าช้าเป็นช่วง ๆ อีกต่อไป
สุดท้ายแล้ว ไม่มีใครผิดคนเดียว
Programmer เขียน Code ถูกต้อง — ไม่มีส่วนไหนที่เป็นปัญหาเลย
Oracle ออกแบบ OEM ให้ทำงานอัตโนมัติ — แต่ Query ที่ OEM ใช้ ไม่ได้ออกแบบมาสำหรับตารางที่ใหญ่มากโดยไม่มีการดูแล
ไม่มีใครตั้งค่าให้ระบบล้างบันทึกเก่าออก — เพราะไม่มีคนดูแลฐานข้อมูลโดยตรง ตารางจึงโตขึ้นทุกวัน อย่างเงียบ ๆ
นี่คือสิ่งที่เกิดขึ้นเมื่อองค์กรไม่มีคนดูแลด้านฐานข้อมูล ไม่ใช่ระบบพังทันที — แต่ค่อย ๆ หนักขึ้นทุกเดือน จนวันหนึ่งผู้ใช้รู้สึกได้ แล้วโทรมาถามว่า "เอายังไงดี"
ข้อมูลดิบจาก AWR และแนวทางตรวจสอบ
ตาราง Segments by Physical Reads จาก AWR จริง (Snap 20656–20660)
| Owner | Tablespace | Object | Physical Reads | %Total |
|---|---|---|---|---|
| SYS | SYSAUX | AUD$ | 7,373,362 | 33.72% |
| (ปกปิด) | (ปกปิด) | RECEIPT | 7,104,510 | 32.49% |
| Total Physical Reads | 21,865,229 | 100% | ||
Segment อันดับ 2 (RECEIPT) คือตาราง Application จริง ซึ่งทีมแยกวิเคราะห์ต่างหาก — มี 2 ปัญหาพร้อมกันใน AWR นี้
Function-Based Index คืออะไร และสร้างให้ตรงกับ OEM อย่างไร
ปัญหา: OEM ใช้ TO_CHAR(timestamp, 'YYYY-MM-DD HH24:MI:SS') ใน WHERE ทำให้ B-Tree Index บน timestamp ใช้ไม่ได้
วิธีแก้: สร้าง Index บน Expression เดียวกับที่ OEM ใช้:
ผลที่ได้: OEM Query เดิมสามารถใช้ Index นี้ได้ทันที ไม่ต้องแก้ SQL ของ OEM เลย
ข้อควรระวัง: SYS.AUD$ เป็น System Object ควรประเมินผลกระทบกับ Write Performance ก่อน เพราะ Index จะเพิ่มภาระตอน INSERT ด้วยทุกครั้งที่ Audit เขียนบันทึก
ขั้นตอนตั้ง Audit Purge Job ด้วย DBMS_AUDIT_MGMT
- ตรวจ Audit Mode:
SELECT name, value FROM v$parameter WHERE name = 'audit_trail' - Initialize:
EXEC DBMS_AUDIT_MGMT.INIT_CLEANUP(audit_trail_type => DBMS_AUDIT_MGMT.AUDIT_TRAIL_AUD_STD, default_cleanup_interval => 720); - กำหนด Archive Timestamp ว่าข้อมูลก่อนเวลานี้ Archive แล้วและพร้อม Purge
- สร้าง Purge Job ให้รันในช่วง Off-Peak ตาม Retention Policy ขององค์กร
- วัดผลจาก AWR รอบถัดไป — ดูที่ Physical Reads ของ SYS.AUD$ ไม่ใช่แค่ขนาด Tablespace
ที่มาของข้อมูลในกรณีศึกษานี้
- ตัวเลขทั้งหมด: มาจาก AWR Report จริง (Snap 20656–20660) ปกปิดชื่อองค์กร, Schema ธุรกิจ และ Hostname
- SQL Text ของ OEM: มาจาก Complete List of SQL Text ใน AWR โดยตรง ไม่ได้แต่งหรือปรับแต่ง
- Oracle 11g: DBMS_AUDIT_MGMT
- Oracle 11g: Automatic Workload Repository
ระบบช้าแบบไม่สม่ำเสมอ หาสาเหตุไม่เจอ?
ทีมเราช่วยวิเคราะห์จาก AWR จนถึง Root Cause จริง ก่อนตัดสินใจแก้
ปรึกษาทีม VT Technology