← Blog

งานอัตโนมัติที่รันสองรอบ — บั๊กที่อาการไม่คงที่และหาสาเหตุยากที่สุด

บั๊กที่ไล่หาสาเหตุยากที่สุดไม่ใช่บั๊กที่ทำให้ระบบพัง แต่เป็นบั๊กที่เกิดบ้างไม่เกิดบ้าง

เราเจอบั๊กแบบนั้นในระบบงานอัตโนมัติ และการไล่ปิดมันให้ขาดกลายเป็นงานที่กินเวลาหลายรีลีสติดกัน

อาการ

รายงานที่เข้ามาไม่เหมือนกันเลยสักเรื่อง

  • บางครั้งลูกค้าได้รับการแจ้งเตือนเรื่องเดียวกันสองครั้ง
  • บางครั้งบิลตามรอบถูกสร้างซ้ำ
  • บางครั้งรายการเดิมถูกประมวลผลสองรอบ

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

สาเหตุ

ระบบของเราถูกออกแบบให้บริการทั้งหมดรวมกันอยู่ในกระบวนการเดียวเพื่อประหยัดหน่วยความจำ ระหว่างการเปลี่ยนผ่านนั้น ตัวจัดการงานอัตโนมัติถูกลงทะเบียนไว้สองที่ — ทั้งในกระบวนการรวมและในกระบวนการแยกที่ยังเหลืออยู่

ผลคือมีตัวจัดการงานสองตัวรันพร้อมกัน ต่างคนต่างหยิบงานเดียวกันไปทำ

ทำไมถึงร้ายแรงกว่าที่ฟัง

งานอัตโนมัติเกือบทั้งหมดถูกเขียนขึ้นภายใต้สมมติฐานเงียบ ๆ ว่ามีตัวเองรันอยู่ตัวเดียว สมมติฐานนี้ไม่เคยถูกเขียนไว้ที่ไหน เพราะตอนที่เขียนโค้ดมันเป็นจริงเสมอ

เมื่อสมมติฐานพัง ปัญหาเกิดสองรูปแบบ

1. ผลซ้ำ

งานที่ส่งอีเมล สร้างเอกสาร หรือหักยอด จะทำสิ่งนั้นสองครั้ง

2. แย่งกันทำงาน

รูปแบบนี้อันตรายกว่า — งานส่วนใหญ่เริ่มด้วยการเช็คก่อนว่ามีใครทำรายการนี้ไปแล้วหรือยัง ถ้าทั้งสองตัวเช็คพร้อมกัน ทั้งคู่จะเห็นว่ายังไม่มีใครทำ แล้วต่างคนต่างทำ

การเช็คแบบนี้ไม่ได้ผิด มันแค่ไม่ปลอดภัยเมื่อมีคนแข่งกัน และช่องว่างระหว่าง “เช็ค” กับ “ทำ” กว้างแค่เสี้ยววินาที ซึ่งเป็นเหตุผลที่บั๊กเกิดเป็นครั้งคราวเท่านั้น

สิ่งที่เราทำ

ขั้นที่ 1 — แก้ต้นเหตุ

ให้เหลือที่เดียวที่รับผิดชอบการรันงานเบื้องหลัง

ขั้นที่ 2 — ไล่ตรวจทั้งระบบ

เราไม่หยุดที่การแก้จุดที่เจอ แต่ไล่ตรวจทุกส่วนของระบบว่ายังมีที่ไหนอีกที่อาจรันซ้อนกันได้ พบอีก 2 จุดและแก้ไปพร้อมกัน

ขั้นตอนนี้สำคัญกว่าขั้นแรก เพราะบั๊กที่อาการไม่คงที่ ถ้าเหลือไว้แม้จุดเดียวจะกลับมาในเวลาที่คาดไม่ถึง และคราวหน้าจะไม่มีใครนึกถึงสาเหตุนี้แล้วเพราะ “แก้ไปแล้ว”

ขั้นที่ 3 — เปลี่ยนจาก “เช็คแล้วทำ” เป็น “จองแล้วทำ”

สำหรับงานที่กระทบเงินโดยตรงอย่างการสร้างบิลตามรอบ เราไม่พึ่งการที่มีตัวจัดการงานตัวเดียว

เปลี่ยนวิธีทำงานเป็นการจองรายการก่อนลงมือ — ตัวที่จองได้เท่านั้นที่จะสร้างบิล ตัวที่จองไม่ทันจะข้ามไปเอง

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

นี่คือความต่างระหว่าง “แก้ให้ไม่เกิด” กับ “ทำให้เกิดไม่ได้”

สิ่งที่เจอเพิ่มระหว่างทาง

การไล่ตรวจรอบนี้ทำให้เจอปัญหาอื่นในระบบงานอัตโนมัติที่ซ่อนอยู่ด้วยกัน

  • งานที่ถูกหยุดกลางคันทิ้งสถานะ “กำลังรัน” ค้างไว้ ทำให้ระบบเข้าใจว่ายังมีตัวรันอยู่แล้วไม่รันอีกเลย — พบว่ามีงานค้างมาตั้งแต่สามเดือนก่อน ตอนนี้ระบบล้างสถานะค้างให้ตอนเริ่มทำงาน
  • งานที่เรียกไปยังระบบภายนอกโดยไม่จำกัดเวลารอ ถ้าปลายทางค้าง งานก็ค้างตาม และเพราะทุกงานใช้คิวร่วมกัน มันจึงบล็อกงานอื่นทั้งหมด — อาการที่เห็นคือระบบเหมือนหยุดทำงานโดยไม่มีข้อผิดพลาดใด ๆ
  • งานที่ล็อกตารางสินค้าทั้งตารางในรายการเดียว ระหว่างนั้นคนที่กำลังบันทึกงานขายจะถูกกันไว้ ยิ่งข้อมูลเยอะยิ่งกันนาน

ทั้งสามเรื่องนี้ไม่เกี่ยวกับบั๊กเดิมโดยตรง แต่เจอเพราะการไล่ตรวจแบบเดียวกัน

ทำไมเราถึงเล่าเรื่องนี้

เพราะเราคิดว่าวิธีจัดการกับบั๊กบอกอะไรเกี่ยวกับทีมได้มากกว่าตัวบั๊กเอง

บั๊กนี้แก้ให้หายอาการได้ในบรรทัดเดียว เราเลือกไม่หยุดตรงนั้น แต่ไล่ตรวจทั้งระบบ แล้วเปลี่ยนวิธีทำงานของส่วนที่กระทบเงินให้ผิดพลาดไม่ได้ตั้งแต่แรก

สำหรับระบบที่ลูกค้าใช้จัดการบัญชีและสต๊อกจริง เราคิดว่านั่นคือมาตรฐานขั้นต่ำที่ควรเป็น

Freeable

บริหารจัดการข้อมูลในองค์กร ครบในที่เดียว

ดูรายละเอียด →

อ่านต่อ

Freeable

รหัสผ่าน 2026 — อักษรพิเศษ มาตรฐานสากล กฎหมายไทย และ 2FA/3FA ที่ควรรู้

กฎรหัสผ่านที่เราคุ้นเคย — ต้องมีตัวใหญ่ ตัวเล็ก ตัวเลข อักษรพิเศษ และเปลี่ยนทุก 90 วัน — ถูกมาตรฐานสากลถอดออกไปแล้ว บทความนี้รวบรวมว่าปัจจุบันมาตรฐานว่าอย่างไร กฎหมายไทยกำหนดอะไร และ 2FA ช่วยตรงไหนที่รหัสผ่านช่วยไม่ได้

Freeable

ค่าหนึ่งค่ามี 4 หน้าที่ — มาตรฐานการแทนค่า เก็บ · ส่ง · คำนวณ · แสดง

ปัญหาเรื่องวันที่ไม่ใช่ปัญหาของวันที่ แต่เป็นหนึ่งตัวอย่างของปัญหาตระกูลเดียวกัน — ค่าหนึ่งค่าถูกใช้ทำ 4 หน้าที่ที่ต่างกัน พอรูปแบบของหน้าที่หนึ่งรั่วไปอีกหน้าที่ ตัวเลขก็เพี้ยนเงียบ ๆ

Freeable

เวลาในระบบมีหลายชั้น และมันไม่ตรงกัน — บทเรียนจากบั๊กที่ไล่ 8 วันแล้วสรุปผิดหลายรอบ

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