---
title: "เวิร์กเกอร์ล่ม แต่การซิงค์ไม่ล่ม"
description: "ฆ่าเวิร์กเกอร์กลางแบตช์แล้วติดตามผู้ติดต่อหนึ่งราย: เคอร์เซอร์ใดถูกบันทึก ทำไมการเขียนที่เล่นซ้ำจึงไม่ลงสองครั้ง และใครเป็นเจ้าของการซิงค์ระหว่างรีสตาร์ต จากนั้นคือเหตุการณ์สองครั้งที่แสดงว่าการกู้คืนเป็นเพียงครึ่งหนึ่งของงาน"
url: https://tajo.io/th/blog/worker-died-sync-didnt/
markdown: https://tajo.io/th/blog/worker-died-sync-didnt.md
lang: th-TH
author: "Set Noa"
author_url: https://tajo.io/th/set-noa/
published: 2026-11-05
updated: 2026-11-05
alternates: {en-US: /blog/worker-died-sync-didnt.md, bg-BG: /bg/blog/worker-died-sync-didnt.md, cs-CZ: /cz/blog/worker-died-sync-didnt.md, de-DE: /de/blog/worker-died-sync-didnt.md, da-DK: /dk/blog/worker-died-sync-didnt.md, es-ES: /es/blog/worker-died-sync-didnt.md, fr-FR: /fr/blog/worker-died-sync-didnt.md, el-GR: /gr/blog/worker-died-sync-didnt.md, hi-IN: /hi/blog/worker-died-sync-didnt.md, id-ID: /in/blog/worker-died-sync-didnt.md, hr-HR: /hr/blog/worker-died-sync-didnt.md, hu-HU: /hu/blog/worker-died-sync-didnt.md, it-IT: /it/blog/worker-died-sync-didnt.md, ja-JP: /jp/blog/worker-died-sync-didnt.md, ko-KR: /kr/blog/worker-died-sync-didnt.md, ar-SA: /ar/blog/worker-died-sync-didnt.md, nl-NL: /nl/blog/worker-died-sync-didnt.md, no-NO: /no/blog/worker-died-sync-didnt.md, pl-PL: /pl/blog/worker-died-sync-didnt.md, pt-BR: /pt/blog/worker-died-sync-didnt.md, ro-RO: /ro/blog/worker-died-sync-didnt.md, ru-RU: /ru/blog/worker-died-sync-didnt.md, sv-SE: /se/blog/worker-died-sync-didnt.md, zh-CN: /zh-cn/blog/worker-died-sync-didnt.md, sl-SI: /sl/blog/worker-died-sync-didnt.md, sr-Latn-RS: /sr/blog/worker-died-sync-didnt.md, tr-TR: /tr/blog/worker-died-sync-didnt.md, ur-PK: /ur/blog/worker-died-sync-didnt.md, vi-VN: /vi/blog/worker-died-sync-didnt.md, sk-SK: /sk/blog/worker-died-sync-didnt.md}
---

[การซิงค์ข้อมูล](https://tajo.io/th/blog/?category=data-sync)

# เวิร์กเกอร์ล่ม แต่การซิงค์ไม่ล่ม

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

กู้คืนการซิงค์ข้อมูลที่ล้มเหลว

จะเกิดอะไรขึ้นกับการซิงค์ที่กำลังทำงาน เมื่อเวิร์กเกอร์ล่มกลางแบตช์?

เคอร์เซอร์เลื่อนเฉพาะเมื่อจบแบตช์ที่เรียบร้อย ดังนั้นเวิร์กเกอร์ที่ถูกฆ่ากลางแบตช์จะทิ้งเคอร์เซอร์ไว้ที่ต้นแบตช์นั้น และการรันครั้งถัดไปจะอ่านหน้าเดิม คีย์การส่งของแต่ละเรคคอร์ดสร้างจากเคอร์เซอร์ของหน้าและตำแหน่งของเรคคอร์ด และสมุดบันทึกการเขียนที่เสร็จแล้วซึ่งเก็บไว้เจ็ดวันป้องกันไม่ให้การเล่นซ้ำลงสองครั้ง สิทธิ์การถือครอง (lease) หนึ่งรายการต่อหนึ่งการซิงค์ป้องกันไม่ให้สองการรันทำงานพร้อมกัน นั่นคือครึ่งที่ง่าย การซิงค์หนึ่งรายการล้มเหลวซ้ำแล้วซ้ำเล่า รันแล้วรันเล่า ก่อนที่จะมีสิ่งใดหยุดมันชั่วคราว และเวิร์กสเปซหนึ่งเงียบอยู่โดยมีข้อผิดพลาดแต่ไม่มีความสำเร็จเลย ก่อนที่จะมีสิ่งใดสังเกตเห็น ตอนนี้จึงมีเบรกเกอร์ที่หยุดการซิงค์ชั่วคราวหลังล้มเหลวติดต่อกันห้าครั้ง และการแจ้งเตือนรายชั่วโมงเมื่อผ่านไปยี่สิบสี่ชั่วโมงโดยไม่มีความสำเร็จ

[เรียนรู้เพิ่มเติม](https://tajo.io/th/blog/worker-died-sync-didnt/#%E0%B8%95%E0%B8%B4%E0%B8%94%E0%B8%95%E0%B8%B2%E0%B8%A1%E0%B8%9C%E0%B8%B9%E0%B9%89%E0%B8%95%E0%B8%B4%E0%B8%94%E0%B8%95%E0%B9%88%E0%B8%AD%E0%B8%AB%E0%B8%99%E0%B8%B6%E0%B9%88%E0%B8%87%E0%B8%A3%E0%B8%B2%E0%B8%A2)

ใน[การบรรยายที่ AI Engineer เผยแพร่เมื่อ 3 ตุลาคม 2026](https://www.youtube.com/watch?v=bRGyYaE0lxI&t=701s) ผู้สนับสนุนนักพัฒนา (developer advocate) ของ Crusoe เริ่มงานเทรน PyTorch บนโหนด A100 สองโหนด จากนั้นผู้บรรยายแจ้งระบบมอนิเตอร์ของเดโมเองว่า GPU ตัวหนึ่งเกิดข้อผิดพลาด XID 79 โหนดนั้นถูกทำเครื่องหมายว่าใช้งานไม่ได้และงานถูกยกเลิก โปรเซสได้รับ SIGTERM และมี “[เวลาสูงสุดสองนาทีในการจัดการ SIGTERM นั้น เพื่อบันทึก checkpoint หรือเขียนล็อกที่ค้างอยู่ออกให้หมด](https://www.youtube.com/watch?v=bRGyYaE0lxI&t=633s)” โหนดสำรองเข้ามาแทน และ “[งาน slurm จะรีสตาร์ต โหลด checkpoint แล้วเทรนต่อจากจุดที่ค้างไว้](https://www.youtube.com/watch?v=bRGyYaE0lxI&t=769s)” ตั้งแต่ต้นจนจบใช้เวลาไม่ถึงสิบห้านาทีเล็กน้อย ไม่มีใครต้องถูกเรียกตัวมาแก้เหตุ

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

นี่คือคำตอบสำหรับ[ตัวรันการซิงค์ของ Tajo เอง](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/) อ่านจากโค้ด ไม่ใช่จากโบรชัวร์ [Reverse ETL](https://tajo.io/th/blog/what-is-reverse-etl/) อธิบายรูปร่างของงานนี้ ส่วนบทความนี้คือสิ่งที่เกิดขึ้นเมื่องานนั้นตาย

## ติดตามผู้ติดต่อหนึ่งราย

การรันอ่านแหล่งข้อมูลทีละหน้า โดยเริ่มจากเคอร์เซอร์ที่บันทึกไว้ ให้เคอร์เซอร์ของหน้าชื่อ `c3` และผู้ติดต่อของเราคือเรคคอร์ดที่ 212 บนหน้านั้น มีสามข้อที่เป็นจริงเกี่ยวกับผู้ติดต่อรายนี้ก่อนที่จะมีการเขียนใด ๆ

ข้อแรก ผู้ติดต่อรายนี้มีคีย์การส่ง คีย์นี้เป็นค่าแฮชของ id ของการซิงค์ แหล่งข้อมูล เคอร์เซอร์ของหน้า ตำแหน่งบนหน้า และตัวเรคคอร์ดเอง เคอร์เซอร์และเรคคอร์ดถูกนำเข้าไปในแฮชและไม่เคยถูกฝังไว้ในคีย์ คีย์จึง[ไม่มีที่อยู่อีเมลติดอยู่](https://tajo.io/th/resources/help/getting-started/understanding-data-sync/)

ข้อสอง การเขียนผ่าน[สมุดบันทึก](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#ledger) (ledger) ไม่ได้ไปยังปลายทางโดยตรง ก่อนเรียกปลายทาง คีย์จะถูกจองไว้ในสถานะรอดำเนินการ เมื่อเขียนสำเร็จ แถวนั้นจะถูกทำเครื่องหมายว่าเสร็จแล้วและเก็บไว้เจ็ดวัน

ข้อสาม เคอร์เซอร์ยังไม่ขยับ เคอร์เซอร์เลื่อนเฉพาะตอนจบแบตช์ เฉพาะเมื่อทุกเรคคอร์ดในแบตช์นั้นลงปลายทางแล้ว และเฉพาะหลังจากการรันพิสูจน์แล้วว่ายังเป็นเจ้าของการซิงค์อยู่

ทีนี้ ฆ่าเวิร์กเกอร์ระหว่างการเขียนกับ checkpoint

เมื่อได้รับ SIGTERM เวิร์กเกอร์คิวทุกตัวจะเคลียร์งานที่ค้างภายใต้เส้นตายร่วมสิบห้าวินาที และโปรเซสจะออกหลังยี่สิบห้าวินาทีไม่ว่าอะไรยังทำงานอยู่ ส่วน systemd ให้เวลาสี่สิบห้าวินาทีก่อนจะฆ่า การรันที่ไม่จบภายในช่วงนั้นยังถูกทำเครื่องหมายว่ากำลังดำเนินการ และเวิร์กเกอร์ถัดไปจะรับต่อผ่านกลไกกู้คืนงานที่ค้าง (stalled-job recovery) ของคิว ในกรณีฆ่าแบบบังคับ (hard kill) จะไม่มีการเคลียร์งานเลย ไม่ว่าทางใด ข้อเท็จจริงสองข้อเดิมยังคงอยู่ ปลายทางมีผู้ติดต่อของเราแล้ว [เคอร์เซอร์](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#cursor)ของเรายังเป็น `c3`

## การเล่นซ้ำ

การรันครั้งถัดไปเริ่มที่ `c3` อ่านหน้าเดิม สร้างคีย์เดิมสำหรับเรคคอร์ดที่ 212 แล้วถามสมุดบันทึก สมุดบันทึกตอบว่าเสร็จแล้ว ปลายทางจะไม่ถูกเรียก ผลลัพธ์ที่เก็บไว้ถูกเล่นซ้ำและการรันทำงานต่อไป ในเส้นทางแบบ bulk ซึ่ง endpoint นำเข้าของ Brevo รับทั้งหน้าในการเรียกครั้งเดียว การตรวจแบบเดียวกันจะทำทีละคีย์ก่อนสร้างคำขอ หน้าที่ทุกคีย์เสร็จแล้วจะไม่ส่งอะไรเลย

นั่นคือเคล็ดลับทั้งหมด และควรอธิบายว่าทำไมมันได้ผล คีย์สร้างจากเคอร์เซอร์ของหน้า ณ จุดเริ่มต้นของแบตช์ ไม่ใช่จากการรันที่บังเอิญทำงานอยู่ การล่ม การลองใหม่ในอีกหกสิบวินาที และการรันตามกำหนดในวันพรุ่งนี้ ล้วน[ได้คีย์เดียวกัน](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#ledger)สำหรับเรคคอร์ดเดียวกัน สมุดบันทึกไม่สนใจว่าใครเป็นผู้ถาม

ทีนี้มาดูต้นทุน [สมุดบันทึกจะลืมหลังเจ็ดวัน](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#ledger) คอมเมนต์ในโค้ดเองบอกว่าเจ็ดวันครอบคลุมการลองใหม่ที่ล่าช้าและการขัดข้องช่วงสั้น และอ้างไว้เพียงเท่านั้น การเล่นซ้ำจากเคอร์เซอร์ที่เก่ากว่านั้นจะเขียนซ้ำ และการรันที่ถูกขัดจังหวะแบบบังคับอาจต้องรอ สิทธิ์การถือครอง (lease) ของการรันที่ตายแล้วค้างอยู่ได้นานถึงสิบห้านาที และในการซิงค์ตามกำหนดเวลา การรันที่สิทธิ์การถือครองว่างอยู่จะ[ถูกกวาดและจัดตารางใหม่ก็ต่อเมื่อเริ่มไปแล้วเกินหนึ่งชั่วโมงเท่านั้น](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#stuck-runs) เดโมของ Crusoe [กลับมาทำงานได้ในเวลาไม่ถึงสิบห้านาที](https://www.youtube.com/watch?v=bRGyYaE0lxI&t=753s) ของเราไม่ได้เป็นเช่นนั้นเสมอไป

## ใครเป็นเจ้าของการซิงค์ระหว่างรีสตาร์ต

การซิงค์หนึ่งรายการมีการรันเป็นเจ้าของได้ครั้งละหนึ่งการรันเท่านั้น การรันจะรับ[สิทธิ์การถือครอง](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#lease)ใน Redis พร้อมโทเค็นของตัวเอง อายุสิบห้านาที และต่ออายุทุกห้านาที ก่อน checkpoint ทุกครั้ง การรันจะยืนยันว่ายังถือสิทธิ์นั้นอยู่ ถ้าไม่ได้ถือแล้วก็จะหยุด การรันจะถูกบันทึกด้วย[ประโยคเรียบง่ายที่ผู้ใช้จะได้อ่าน](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#failures): “The run lost its slot part-way through and stopped to avoid writing twice.” (การรันเสียสิทธิ์กลางทางและหยุดเพื่อไม่ให้เขียนซ้ำสองครั้ง) การรันที่สองที่ชนกับเจ้าของที่ยังทำงานอยู่จะไม่ถูกลองใหม่ มัน[จบด้วย](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#failures) “Another run of this sync was already in progress” (มีการรันอื่นของการซิงค์นี้กำลังทำงานอยู่แล้ว) และการรันตามกำหนดครั้งถัดไปจะเริ่มตามปกติ

ความรับผิดชอบในการแก้ไขก็ถูกเขียนไว้เช่นกัน [รหัสความล้มเหลว](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#failures)ทุกตัวจับคู่กับประโยคหนึ่งว่าเกิดอะไรขึ้น ประโยคหนึ่งว่าต้องทำอะไรต่อ และเจ้าของหนึ่งราย: คุณหรือ Tajo ปลายทางที่ปฏิเสธทุกเรคคอร์ดเพราะการแมปผิดเป็นเรื่องของคุณ [สิทธิ์การถือครองที่หายไปเป็นเรื่องของเรา](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#failures) หน้าของการรันจะแสดงขั้นตอนถัดไป ส่วน[คู่มือการกู้คืนการซิงค์](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#failures)จะระบุว่าเป็นของฝ่ายใด

จนถึงตรงนี้คือครึ่งที่ง่าย การล่มหนึ่งครั้งเสียแค่การเล่นซ้ำหนึ่งครั้ง และไม่มีอะไรลงสองครั้ง เหตุการณ์สองครั้งสอนอีกครึ่งหนึ่ง

## ล้มเหลวแล้วล้มเหลวอีก

การซิงค์หนึ่งรายการล้มเหลวซ้ำแล้วซ้ำเล่า ไม่ใช่ในลูปถี่ ๆ แต่ครั้งละหนึ่งรอบของตัวจัดตาราง รันแล้วรันเล่า ด้วยข้อความเดิมทุกครั้งว่า custom id มีเครื่องหมายโคลอนไม่ได้ การรันไม่เคยไปถึงปลายทาง มันตายระหว่างถูกเข้าคิว ก่อนที่ตัวรันใดจะเห็น ดังนั้นการแจ้งเตือนที่ผูกกับตัวรันจึงไม่มีอะไรให้ผูกเลย

ไม่มีอะไรเฝ้าดูความล้มเหลวที่ต่อเนื่องนั้น นั่นคือข้อค้นพบทั้งหมด

ทางแก้คือเบรกเกอร์ หลังความล้มเหลวที่ถูกบันทึกทุกครั้ง มันจะอ่านห้าการรันล่าสุดที่จบแล้วของการซิงค์ นับตั้งแต่การซิงค์ถูกแก้ไขครั้งล่าสุด ถ้าทั้งห้าเป็นข้อผิดพลาด มันจะหยุดการซิงค์ชั่วคราว เขียนแถว audit หนึ่งแถวพร้อมเหตุผล `circuit_breaker_tripped` และส่งการแจ้งเตือนระดับวิกฤตหนึ่งครั้ง ความต่อเนื่องของความล้มเหลวคำนวณจากการรันที่เก็บไว้ ไม่ใช่จากตัวนับในเวิร์กเกอร์ ความล้มเหลวที่ถูกบันทึกจากเส้นทางใดก็นับ รวมถึงความล้มเหลวตอนเข้าคิวที่เป็นต้นเหตุของเหตุการณ์นั้น คอมเมนต์ในโค้ดบอกว่ามันจะหยุดเหตุการณ์นั้นได้ที่การรันครั้งที่ห้า ความสำเร็จหนึ่งครั้งจะรีเซ็ตความต่อเนื่อง การยกเลิกการหยุดชั่วคราวจะตั้งเบรกเกอร์ใหม่ แทนที่จะทำให้มันตัดอีกครั้งจากแถวเก่า [คู่มือคอนเนกเตอร์ Shopify](https://tajo.io/th/docs/ecommerce-platforms/shopify/) บอกสิ่งเดียวกันในบรรทัดเดียว: หลังการรันล้มเหลวติดต่อกันห้าครั้ง การซิงค์จะหยุดตัวเองชั่วคราวและหน้าของการซิงค์จะแสดงข้อผิดพลาดล่าสุด

สิ่งที่เบรกเกอร์ไม่ได้ทำคือการแก้ไขอะไร Crusoe เปลี่ยนโหนดและรีสตาร์ตงานโดยไม่ต้องถาม Tajo หยุดและถาม: การซิงค์ที่หยุดชั่วคราวจะหยุดอยู่อย่างนั้นจนกว่าคนจะแก้ต้นเหตุและ[เผยแพร่การซิงค์อีกครั้ง](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#pause) ค่าเริ่มต้นที่ระมัดระวังนี้เป็นความตั้งใจ: การลองใหม่อัตโนมัติของการซิงค์ที่เขียนลงข้อมูลลูกค้าก็คือการเขียนในตัวมันเอง

## ความเงียบที่ไม่มีใครเห็น

ข้อโต้แย้งนี้สมเหตุสมผล และเป็นอย่างนี้: “เบรกเกอร์ที่หยุดชั่วคราวหลังล้มเหลวห้าครั้งก็น่าจะจับเหตุการณ์ที่สองได้เหมือนกัน ทำไมต้องสร้างตัวเฝ้าดูตัวที่สอง?” เพราะเหตุการณ์ที่สองไม่ได้ดูเหมือนความล้มเหลว เป็นเวลานานที่เวิร์กสเปซหนึ่งมีการซิงค์ที่เปิดใช้งาน มีแถวข้อผิดพลาดกองเพิ่มขึ้นเรื่อย ๆ และไม่มีความสำเร็จเลยแม้แต่ครั้งเดียว และไม่มีอะไรแจ้งเตือน ทุกสัญญาณที่มีอยู่ผูกกับกิจกรรม: การรันล้มเหลว webhook เข้ามา งบประมาณถูกใช้เกิน ความสำเร็จที่เป็นศูนย์ไม่ใช่เหตุการณ์ มันคือการไม่มีเหตุการณ์ และเบรกเกอร์ทำงานเฉพาะเมื่อมีการบันทึกความล้มเหลว ตัวจัดตารางที่ตายแล้ว คิวที่ติดขัด เวิร์กเกอร์ที่ไม่เคยบูตขึ้น สิ่งเหล่านี้ไม่บันทึกอะไรเลย และเบรกเกอร์ก็ไม่เคยตื่น

ด้ามจับ dead-man ของหัวรถจักรทำงานกลับกัน คนขับต้องกดมันไว้ตลอด และความเงียบจะหยุดรถไฟ เวอร์ชันสำหรับการซิงค์[ทำงานชั่วโมงละครั้ง](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#hourly-check) ที่นาทีที่สิบสามของทุกชั่วโมง สำหรับทุกเวิร์กสเปซที่มีการซิงค์ที่เปิดใช้งาน มันถามคำถามเดียว: มีการรันใดสำเร็จในยี่สิบสี่ชั่วโมงที่ผ่านมาหรือไม่? เวิร์กสเปซที่การซิงค์ที่เปิดใช้งานเก่าที่สุดถูกเปิดเมื่อไม่ถึงหนึ่งวันก่อนจะถูกปล่อยไว้ เพราะยังไม่มีเวลาหนึ่งวันที่จะสำเร็จ เวิร์กสเปซที่เก่ากว่านั้นและเงียบจะได้รับการแจ้งเตือนระดับวิกฤตหนึ่งครั้ง การแจ้งเตือนบอกว่าเป็นความเงียบแบบใด: มีการรันถูกบันทึกแต่ไม่มีครั้งใดสำเร็จ หรือไม่มีการรันถูกบันทึกเลย มันทำงานครั้งเดียวต่อเหตุการณ์ ตัวทำเครื่องหมายใน Redis จะปิดมันไว้จนถึงการรันที่สำเร็จครั้งแรก จากนั้นจะถูกล้าง เพื่อให้เหตุการณ์ครั้งต่อไปแจ้งเตือนได้อีก

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

## สิ่งที่สร้างแล้ว และสิ่งที่ยังไม่ได้สร้าง

สร้างแล้ว ณ เวลาที่เขียน:

- เคอร์เซอร์ถูกบันทึกเมื่อจบทุกแบตช์ที่เรียบร้อย และบันทึกอีกครั้งเมื่อเกิดการล่ม
- คีย์การส่งของทุกเรคคอร์ดสร้างจากเคอร์เซอร์ของหน้าและตำแหน่งของเรคคอร์ด และถูกตรวจกับ[สมุดบันทึกเจ็ดวัน](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#ledger)ก่อนการเรียกปลายทางทุกครั้ง
- [สิทธิ์การถือครอง](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#lease)หนึ่งรายการต่อหนึ่งการซิงค์ อายุสิบห้านาที
- [ลองได้ห้าครั้ง](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#retries)ต่อการรัน โดยเว้นระยะถอยออกเริ่มจากหกสิบวินาที
- [เบรกเกอร์](https://tajo.io/th/resources/help/getting-started/understanding-data-sync/)ที่หยุดการซิงค์ชั่วคราวหลังล้มเหลวติดต่อกันห้าครั้ง และบันทึกเหตุผล
- [การแจ้งเตือนรายชั่วโมง](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#hourly-check)เมื่อผ่านไปยี่สิบสี่ชั่วโมงโดยไม่มีความสำเร็จ

ยังไม่ได้สร้าง และควรรู้ก่อนพึ่งพา:

- dead-man เฝ้าดูเวิร์กสเปซ ไม่ใช่การซิงค์ การซิงค์ที่ปกติหนึ่งรายการจะบังการซิงค์อีกรายการที่เงียบอยู่ในเวิร์กสเปซเดียวกัน
- การแจ้งเตือนของมัน[ไปถึงผู้ดูแลระบบของ Tajo](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#hourly-check): บรรทัดล็อกเสมอ และ Sentry, webhook หรืออีเมลในที่ที่ตั้งค่าไว้ มันไม่ปรากฏบนหน้าของการซิงค์ แต่การหยุดชั่วคราวของเบรกเกอร์ปรากฏ
- ไม่มีอะไรรีสตาร์ตการซิงค์ที่หยุดชั่วคราว คนเป็นผู้ทำ
- การกู้คืนหลังการฆ่าแบบบังคับไม่เร็ว สิทธิ์การถือครองอาจค้างได้สิบห้านาที และ[การกวาดรอหนึ่งชั่วโมง](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#stuck-runs)
- เกณฑ์ทั้งสอง คือห้าความล้มเหลวและยี่สิบสี่ชั่วโมง เป็น[การตั้งค่าระดับการติดตั้งใช้งาน](https://tajo.io/th/resources/help/troubleshooting/recover-a-stuck-or-failed-sync/#limits) คุณตั้งค่าแยกต่อการซิงค์ไม่ได้

[สายยาวของขั้นตอนที่เกือบสมบูรณ์แบบก็ยังล้มเหลว](https://tajo.io/th/blog/almost-perfect-steps-unreliable-chain/) ทางออกคือกำหนดสถานะปลายทางแล้วตรวจหามัน บทความนี้คือครึ่งเชิงปฏิบัติการของเรื่องนั้น กำหนดว่าการรันที่ตายทิ้งอะไรไว้ และตรวจหาความว่างเปล่าที่ความเงียบทิ้งไว้

ประโยคปิดของ Crusoe คือ “[ความล้มเหลวเป็นสิ่งที่หลีกเลี่ยงไม่ได้](https://www.youtube.com/watch?v=bRGyYaE0lxI&t=955s)” ของเราก้าวไปอีกขั้นหนึ่ง การล่มคือครึ่งที่ง่าย เพราะมันทิ้งแถวไว้ ความเงียบคือครึ่งที่เราต้องออกไปตามหา

## คำถามที่พบบ่อย

**จะเกิดอะไรขึ้นกับการซิงค์ที่กำลังทำงาน เมื่อเวิร์กเกอร์ล่มกลางแบตช์?**

เคอร์เซอร์ยังชี้ไปที่จุดเริ่มต้นของแบตช์ที่ถูกขัดจังหวะ เพราะ Tajo เลื่อนเคอร์เซอร์ก็ต่อเมื่อแบตช์ลงปลายทางเรียบร้อยแล้วเท่านั้น การรันครั้งถัดไปจึงอ่านหน้าเดิมอีกครั้ง แต่ละเรคคอร์ดมีคีย์การส่ง (delivery key) ที่สร้างจากเคอร์เซอร์ของหน้าและตำแหน่งของเรคคอร์ด และมีสมุดบันทึก (ledger) ที่เก็บการเขียนที่เสร็จแล้วทุกรายการไว้เจ็ดวัน เรคคอร์ดที่เขียนไปแล้วจึงถูกเล่นซ้ำจากสมุดบันทึก แทนที่จะถูกส่งไปยังปลายทางเป็นครั้งที่สอง

**ทำไมการซิงค์ที่เล่นซ้ำจึงไม่เขียนผู้ติดต่อรายเดิมสองครั้ง?**

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

**การแจ้งเตือนแบบ dead-man สำหรับการซิงค์คืออะไร?**

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

## บทความที่เกี่ยวข้อง

### [หกกฎสำหรับการซิงค์ที่ทำงานตอนไม่มีใครเฝ้าดู](https://tajo.io/th/blog/six-rules-unattended-sync/)

6 พ.ย. 2569 · 2 นาทีอ่าน

7 ส่วน

### [เวิร์กโฟลว์ที่อยู่ระหว่างกล่องในแผนภาพ](https://tajo.io/th/blog/the-workflow-between-the-boxes/)

8 ต.ค. 2569 · 1 นาทีอ่าน

ระเบียนร้าน → ผู้ปฏิบัติงานแก้ → ปลายทางอีเมล

### [การผสาน Brevo: เลือกการเชื่อมต่อที่ตรวจสอบได้](https://tajo.io/th/blog/brevo-connector-guide/)

19 ส.ค. 2569 · 1 นาทีอ่าน

6 ส่วน
