ภาพรวม
ค้นประวัติ git 19-29 ต.ค. 2026 แล้ว: มี commit ติดป้าย perf จริงเพียง 1 ตัว (56c38867) ที่เหลือเป็นการกันภาระ/การแย่งล็อกที่มาจากบั๊กความถูกต้อง ไม่ใช่การจูนความเร็ว ค้นคำ N+1 / round-trip / bulk / one query ในข้อความ commit ไม่พบ commit ที่ประกาศแก้ N+1 จึงไม่แต่งเคส บันทึกนี้เก็บเฉพาะที่พิสูจน์ได้ และแยก near-miss ไว้ชัด
อาการ
- A) แค็ตตาล็อก Balloon Help อยู่ใน RAM ฝั่ง client ทั้งก้อน (ตามชื่อ commit)
- B) prewarm แผนที่ (monitormap tile) รับ POST ได้โดยไม่ตรวจ session และงานเบื้องหลังซ้อนกันได้ (ตามข้อความ commit)
- C) บันทึกเอกสารสต็อก/ต้นทุนพร้อมกัน deadlock
40P01; บันทึกบัญชีต้องรอ rebuild GL ที่ถือล็อกนานได้ถึง 60 วินาที - D) หน้า BuySaleInformation "เฉพาะมียอด" กรองหลัง
LIMIT 100รายการที่ควรโชว์หาย (M9)
สาเหตุ (root cause)
- A) แค็ตตาล็อกเป็นไฟล์เดียวที่ bundle ไปกับ client (ตามชื่อ commit
56c38867"zero client catalog RAM"; diff route ตรวจแล้ว) - B) handler รับ POST โดยไม่ตรวจ session และรันบน context ไม่มีเพดานเวลา (ข้อความ + diff
4de91436ตรวจแล้ว) - C) การ update
ic_trans_detailของเอกสารอื่นบน item เดียวกันโดยลำดับล็อกไม่แน่นอน (comment ในservice.goของ4341ae81); GL rebuild ถือ tx ยาวและบันทึกแบบแชร์ล็อกต้องรอ (comment ของac839a65) - D) ตัวกรองอยู่ฝั่ง client หลังตัดแถว (ข้อความ
7dc1b3a6)
วิธีแก้
- A)
56c38867: แยก JSON ตามโมดูล (common/ic/ar_ap/trans/gl_tax), ให้ server สร้างMapแล้วตอบ/api/help?keys=ทีละ 1 entry พร้อมCache-Control: max-age=300(จำกัด key <=120 ตัวอักษร, <=5 key) - B)
4de91436: POST ต้องมี session, ใช้atomic.Boolกัน prewarm ซ้อน (single-flight), เพดาน 10 นาที (prewarmJobTimeout) และมีเทสต์prewarm_test.go(anonymous = 401) - C)
4341ae81: ล็อกpg_advisory_xact_lockต่อ item เรียงตามรหัสก่อนแก้ detail (lockStockItems);ac839a65: ล็อกgl_journal:rebuildแบบ exclusive (rebuild) กับ shared (บันทึก) พร้อมคอมเมนต์ระบุเพดานและทางอัปเกรดเป็นกุญแจรายงวด - D)
7dc1b3a6: ย้ายตัวกรองเข้า SQL. ฟีเจอร์ใหม่ (ไม่ใช่การแก้บั๊ก)3e69b2b5: MCP อ่านอย่างเดียวคืนรูปcompactเป็นค่าเริ่มต้นและตั้งเพดานแถวต่อ tool (เริ่ม 50-100, สูงสุด 200-500)
commit ที่เกี่ยวข้อง
56c38867 (perf: help), 4de91436 (prewarm), 4341ae81, ac839a65 (ล็อก), 7dc1b3a6 (M9, ตั้งค่ารายการต่อแท็บ), 3e69b2b5 (MCP). Near-miss: bbf81811 ข้อความระบุ "5-min watcher interval" แต่ stat ไม่มีไฟล์ watcher จึงไม่นับเป็นงาน perf ของระบบ; ADR-0008/0009 (/query/batch อ่านสูงสุด 20 statement, /query/execBatch เขียน atomic) เน้นความถูกต้อง ไม่ใช่การจูนความเร็ว (ตามเนื้อ ADR); ตัวเลข "ประหยัด 55-75% token" เป็นคอมเมนต์ในโค้ด ไม่ได้วัดซ้ำ
โค้ดปัจจุบันที่ป้องกัน
frontend/src/app/api/help/route.ts:26,291(SERVER_HELP_INDEX,GET; ไฟล์โตขึ้นหลังเพิ่มสลับภาษา47fce10e), ข้อมูลfrontend/src/config/help/data/*.jsonbackend/internal/adapter/inbound/http/monitormap/handler.go:64-70,573(prewarmRunning,prewarmJobTimeout,CompareAndSwap)backend/internal/application/process/service.go:990,992,1356,1365(stockRebuildLock,lockStockItems,glRebuildLock)backend/internal/adapter/inbound/http/mcp/compact.go:10(FormatCompact),gateway.go:1190-1298(เพดานlimit)backend/internal/domain/query/query.go:35-40(เพดานจำนวน statement ของ batch)
บทเรียน / กฎที่ได้
- งานเบื้องหลังที่ผู้ใช้สั่งได้ต้องมี 3 อย่างเสมอ: ตรวจสิทธิ์, single-flight, เพดานเวลา
- ล็อกหลายตัวต้องเรียงลำดับเดียวกันทุกที่ (sorted item codes) ถ้าถือล็อกยาว ต้องเขียนเพดานและทางอัปเกรดไว้ใน comment
- ข้อมูลอ้างอิงขนาดใหญ่ให้ server ค้นแล้วส่งทีละ entry พร้อม cache header แทนแพ็กไปทั้งก้อน
- กรองก่อน
LIMITเสมอ มิฉะนั้นผลที่เห็นไม่ครบโดยไม่มีข้อผิดพลาด - ช่องทางให้ AI/MCP ต้องแคบ (compact + เพดานแถว) ตัวเลขประหยัดเป็นค่าประมาณ
- ไม่มี commit ใดวัดก่อน-หลัง จึงไม่มีตัวเลขประสิทธิภาพให้อ้าง
ดูเพิ่ม
บทเรียนบั๊กการทำงานพร้อมกันและ advisory lock (Concurrency & Advisory Locks) · บทเรียนการล็อกการเขียนผ่าน query gateway (Query Gateway Write Lockdown) · บทเรียน เครื่องมือรายงานให้ตรง C# (Report engine parity) · แท็บ MDI: คีย์ลัดแท็บซ่อน, listKey ชน, กันทิ้งข้อมูล (Hidden-Tab Hotkeys & Dirty Guard) · บทเรียนธุรกรรมอะตอมมิกและ error ที่ถูกกลืน (Atomic Transactions & Swallowed Errors) · history-overview
ที่มาในโค้ด
repo smlaiaccount (อ่านอย่างเดียว): frontend/src/app/api/help/route.ts, backend/internal/adapter/inbound/http/{monitormap,mcp}/, backend/internal/application/process/service.go, diff ของ 56c38867, 4de91436, 4341ae81, ac839a65