
剛剛從大促的戰(zhàn)場中緩過神來就被開發(fā)同事拉到一邊“Canal 起不來了報錯Could not find first log file name in binary log index file而且看起來是啟動直接掛日志刷了幾行就沒了。”我當時第一反應是這哥們怕不是把 binlog 文件手動刪了或者把 Canal 的位點配置改到很久以前了。這類報錯在 Canal 的排障群里其實屬于高頻問題但它每次出現(xiàn)都伴隨著一個很尷尬的事實——大部分同學對 Canal 啟動時“如何定位 binlog 文件”這塊機制并不清楚遇到報錯只能靠猜運氣不好還得在測試環(huán)境折騰半天。這篇文章我就把這個報錯徹底拆開。從報錯出現(xiàn)的真實場景、Canal 定位 binlog 的完整流程到一步步排查的命令、能直接落地的修復方案以及我踩過幾次坑之后總結的預防手段一次說清楚。不管你是剛上手 Canal 的新手還是已經(jīng)被這個報錯折磨過的老手這篇應該都能幫你省下不少時間。1. 這個報錯長什么樣從啟動日志到實際影響1.1 完整的報錯現(xiàn)場與我的復現(xiàn)環(huán)境先看一個典型的報錯日志通常出現(xiàn)在 Canal 實例啟動后幾秒內(nèi)MysqlEventParser初始化階段2024-11-18 10:23:45.123 ERROR com.alibaba.otter.canal.parse.inbound.mysql.MysqlEventParser - parse failed com.alibaba.otter.canal.parse.exception.CanalParseException: Could not find first log file name in binary log index file at com.alibaba.otter.canal.parse.inbound.mysql.MysqlBinlogParser.findStartPosition(MysqlBinlogParser.java:...) at com.alibaba.otter.canal.parse.inbound.mysql.MysqlEventParser.start(MysqlEventParser.java:...) ...如果你用的是 Canal 1.1.x 系列報錯信息基本就是這個樣子。核心異常信息只有一句話在 binlog index 文件里找不到第一個 log file name。我當時復現(xiàn)這個問題的環(huán)境大概是這樣的MySQL 8.0.28binlog 開啟binlog_formatROWCanal 1.1.6部署方式為單機直接啟動沒有走 Canal Admin下游消費端是 Kafka業(yè)務方說前一天晚上做過一次大數(shù)據(jù)量清理Canal 配置里寫的是journalNamemysql-bin.000126position 是某個具體偏移量表面上看似乎沒什么問題但重啟之后直接就拋了這個異常。1.2 為什么“文件名找不到”會卡死整個通道很多同學第一次看到這個報錯會覺得困惑Canal 不是直接連上 MySQL 去拉 binlog 嗎最多就是位點不對怎么會直接拋異常起不來這里要理解一個關鍵點Canal 的MysqlBinlogParser在向 MySQL 發(fā)起 dump 請求之前先要在本地做一次“文件定位”。它需要知道你配置的位點或者上次記錄的位點落在哪一個 binlog 文件、偏移量是多少。而定位動作依賴兩個東西你提供的journalNamebinlog 文件名MySQL 服務器上的 binlog index 文件通常叫binlog.index如果 Canal 拿著文件名去binlog.index里逐行匹配發(fā)現(xiàn)這個文件根本不在清單里它就不會傻傻地繼續(xù)請求 MySQL——因為即便請求了MySQL 也只會返回錯誤。Canal 的設計在這里選擇了直接拋出異常讓運維人員盡快介入。這個行為的另一層含義是這個報錯說明 Canal 自身邏輯沒壞真正壞的是“Canal 認知中的位點”和“MySQL 當前實際的 binlog 狀態(tài)”這兩者之間的同步關系。所以排查思路也應該圍繞這個關系展開而不是去懷疑 Canal 程序本身。2. Canal找binlog的完整鏈路從配置位點到索引文件解析2.1 啟動時Canal到底做了什么要搞懂這個報錯我建議先跟著 Canal 的啟動流程走一遍。一個 Canal 實例啟動后CanalLauncher會先加載配置然后創(chuàng)建CanalInstanceWithManager或直連模式下的CanalInstance接著調(diào)用start()方法。MysqlEventParser開始工作后第一件事不是連 MySQL而是構造MysqlBinlogParser然后調(diào)用它的findStartPosition()方法。findStartPosition的輸入就是你配置的位點信息輸出則是一個“起始文件偏移量”的組合。具體流程可以簡化為如果配置了 GTID 模式先從 MySQL 查詢當前 GTID 集合走 GTID 定位邏輯如果配置了 timestampCanal 會調(diào)用 MySQL 的BINLOG相關接口實際上是通過show binlog events或解析 index 文件找到小于等于這個時間戳的 binlog 事件位置如果配置了journalName position那 Canal 就會拿著這個文件名去 binlog index 文件里匹配匹配成功后再結合 position 確認起始點如果沒有配置任何位點Canal 會去查show master status從當前 binlog 文件的最開頭開始消費。我們的報錯發(fā)生在第 3 步拿著配置里的journalName去 binlog index 文件里匹配結果沒匹配到。2.2 哪些配置和狀態(tài)決定了“first log file name”Canal 定位 binlog 時涉及的配置項和運行時狀態(tài)比大多數(shù)人想象的要復雜一些。先從instance.properties文件看起和位點相關的核心配置有這么幾個配置項含義典型示例canal.instance.master.journal.namebinlog 文件名mysql-bin.000126canal.instance.master.positionbinlog 文件內(nèi)的偏移量4或120canal.instance.master.timestamp按時間戳定位1699999999canal.instance.master.gtid按 GTID 定位xxxx:1-100canal.instance.master.auto.position是否自動定位false這里有個很容易被忽略的細節(jié)Canal 的位點并不僅僅來自instance.properties。如果 Canal 實例運行過那么meta.dat文件默認在conf/實例名/meta.dat或 canal 的meta目錄下里會持久化最近一次成功 dump 的位點。重啟時 Canal 會優(yōu)先讀取meta.dat中記錄的位點而不是instance.properties里的配置。這意味著什么意味著哪怕你改對了instance.properties只要meta.dat沒清掉Canal 的findStartPosition還是可能用舊位點去匹配 binlog index 文件。這個坑我見過不止一次有人說“我明明改了配置里的 journalName怎么還是報同樣的錯”十有八九是meta.dat在搗鬼。2.3 binlog index 文件的真實作用與常見誤解MySQL 的 binlog index 文件默認叫binlog.index位于datadir目錄下。它本質(zhì)上就是一個純文本文件每行記錄一個 binlog 文件的完整路徑名比如/data/mysql/logs/mysql-bin.000120 /data/mysql/logs/mysql-bin.000121 /data/mysql/logs/mysql-bin.000122MySQL 在生成新 binlog、清理舊 binlog、執(zhí)行flush logs時都會同步更新這個文件。Canal 解析 index 文件時會把每一行的文件名提取出來和它要找的journalName做匹配。這里有一個常見的誤解很多人以為show binary logs的輸出就等同于 binlog.index 的內(nèi)容。從結果上看兩者確實高度一致但底層邏輯并不相同。show binary logs需要連接 MySQL 實例而 Canal 解析 index 文件是在本地文件層面完成的不需要依賴 MySQL 的連接狀態(tài)。所以當 MySQL 的 binlog.index 文件被誤刪、被清空、路徑寫錯或者文件內(nèi)容與實際 binlog 文件不一致時Canal 即使能連上 MySQL也會在這一步直接掛掉。還有一個需要特別注意的點Canal 匹配的是“文件名”不是完整路徑。正常情況下 index 文件里記錄的是完整路徑Canal 會把行長這樣解析后取最后一段。但如果你手動編輯 index 文件時路徑分隔符、換行符搞錯了或者文件末尾缺了換行Canal 解析出來的文件名就可能變成“帶后綴的臟數(shù)據(jù)”匹配必然失敗。我見過一個極端案例某同學的 binlog.index 文件是用 Windows 編輯器改過的行尾帶了\r字符Canal 死活匹配不上日志里看不出來最后用cat -A才發(fā)現(xiàn)每行末尾有個^M。這種問題排查起來非常隱蔽。3. 由淺入深的排查過程五步定位根因3.1 第一步先看MySQL側binlog到底還剩什么遇到報錯我的習慣是先從 MySQL 側確認“當前實際存在哪些 binlog 文件”這是最基礎的事實依據(jù)。登錄 MySQL執(zhí)行SHOW BINARY LOGS;這個命令會列出當前所有可用的 binlog 文件及大小。你需要拿這份清單和 Canal 報錯里涉及的文件名做對比。如果清單里壓根沒有配置中的那個文件那問題基本就明確了Canal 要的文件早就被清理了。還有一個更精細的查詢方式可以同時看到 binlog 文件的寫入時間SHOW BINARY LOGS\GMySQL 8.0 的輸出還會帶上Log_name、File_size、Encrypted等字段。在排查“文件為什么沒了”時通常還要結合 binlog 的過期配置一起看SHOW VARIABLES LIKE binlog_expire_logs_seconds; SHOW VARIABLES LIKE expire_logs_days; SHOW VARIABLES LIKE max_binlog_size;MySQL 8.0 里expire_logs_days已經(jīng)廢棄統(tǒng)一用binlog_expire_logs_seconds。如果你發(fā)現(xiàn) binlog 文件的保留時間極短比如 3600 秒而 Canal 消費端又因為各種原因斷過一段時間位點很容易就跑到 binlog 保留范圍之外。3.2 第二步核對Canal配置位點與binlog清單確認 MySQL 側的文件清單之后接下來就是核對 Canal 的配置位點。找到 Canal 實例的配置文件默認路徑是conf/你的實例名/instance.properties重點看這幾個配置canal.instance.master.address127.0.0.1:3306 canal.instance.master.journal.namemysql-bin.000126 canal.instance.master.position4 canal.instance.master.timestamp canal.instance.master.gtid將journal.name和position與第一步拿到的SHOW BINARY LOGS清單對比。如果journal.name對應的文件已經(jīng)不在清單里說明位點落后了。但這里要格外小心配置文件里寫的位點不一定是實際生效的位點。如果 Canal 實例啟動過meta.dat里的持久化位點優(yōu)先級更高除非你配置了auto.positiontrue。所以無論配置里寫的是什么我建議都去看一眼meta.dat的實際內(nèi)容。meta.dat是一個文本文件內(nèi)容類似{journalName:mysql-bin.000110,position:123456,timestamp:1699999999000,gtid:}如果這個文件里的journalName已經(jīng)是個“遠古”文件那你真正該改的就是它而不是instance.properties。3.3 第三步檢查meta.dat與snapshot的內(nèi)存位點meta.dat的問題前面提過了這里展開細說。Canal 在運行過程中每消費一批 binlog 事件都會把位點信息更新到內(nèi)存中并定期刷寫到meta.dat。如果你在 Canal 運行期間強制 kill 進程或者直接刪除meta.dat重啟Canal 會回退到instance.properties的配置位點或者auto.position自動定位。這就會產(chǎn)生一個現(xiàn)象同一個實例目錄上次運行記錄了一個位點你改了配置文件的位點但 meta.dat 還賴著舊位點不放。于是你看著配置明明改對了啟動還是報“找不到文件”。處理方式其實很簡單修改位點相關的配置時把meta.dat一并刪除或者改名備份讓 Canal 重新以配置文件為準進行初始化。但有兩點必須注意刪meta.dat可能會導致重復消費或跳躍消費。如果下游是消息隊列并且業(yè)務不允許重復你需要評估后再操作。某些 Canal 版本里meta.dat的路徑可能在conf/實例名/meta.dat也可能在 canal 運行目錄下的meta/文件夾里。不同部署方式路徑不一致別找錯地方。3.4 第四步確認權限與GTID模式的影響排除了位點問題后如果還是報同樣的錯誤就要把視線轉(zhuǎn)移到 Canal 連接 MySQL 的賬號權限、以及 MySQL 的復制模式配置上。Canal 要正常拉取 binlog賬號至少需要REPLICATION SLAVE、REPLICATION CLIENT兩個權限。權限不足時的報錯往往不是直接提示權限而是在后續(xù)流程中間接暴露出來。但有一種情況比較特殊如果 Canal 嘗試通過SHOW MASTER STATUS獲取當前位點而賬號沒有REPLICATION CLIENT權限拿到的結果可能是空的Canal 的定位邏輯就會走進異常分支。另外GTID 模式的影響也不能忽略。檢查 MySQL 是否開啟了 GTIDSHOW VARIABLES LIKE gtid_mode;如果開啟了ON或ON_PERMISSIVE而 Canal 的配置還停留在非 GTID 的journalName position方式偶爾也會出現(xiàn)定位異常。雖然 Canal 本身支持兩種模式混用但在 GTID 已經(jīng)開啟的環(huán)境里我建議優(yōu)先把canal.instance.master.gtid配上或者讓 Canal 自動從show master status中讀取當前 GTID。當然這個步驟的作用主要是“排除干擾因素”真正因為權限或 GTID 直接導致Could not find first log file name的情況相對較少但既然排查就排查徹底不然修好了也會留下隱患。3.5 第五步檢查binlog.index文件本身是否損壞如果以上四步都沒發(fā)現(xiàn)問題——MySQL 清單里有這個文件、配置和 meta.dat 都跳過了、權限沒問題、GTID 模式也正常——那就要懷疑 binlog.index 文件本身了。在 MySQL 服務器上找到binlog.index# 通常位于 datadir 目錄下 find / -name binlog.index 2/dev/null然后用文本方式查看內(nèi)容cat /data/mysql/lib/mysql/binlog.index重點關注幾點文件是否為空文件里記錄的文件名和實際存在的 binlog 文件是否一一對應每行結尾是否有異常的隱藏字符文件的屬主和權限Canal 側解析的是 MySQL 所在機器上的 index 文件還是遠程通過協(xié)議獲取的 index 文件取決于你是否把 index 文件放到了 Canal 能訪問的位置。還有一個容易被忽略的場景binlog 文件被手動rm過但 index 文件沒有同步更新。這種情況下index 文件里雖然還記錄著文件名但實際文件早沒了。Canal 解析 index 文件時能找到這個名字接下來向 MySQL 發(fā) dump 請求時MySQL 才會報文件不存在。這類問題的報錯通常不是“找不到 first log file name”而是后續(xù) dump 階段的錯誤但如果你看到 index 文件里列出了很多不存在的文件說明清理工作做得不規(guī)范遲早會出事。4. 三種有效修復方案與風險權衡4.1 方案A重置Canal位點到當前binlog起點這是最常用、也最直接的修復方式。適用場景Canal 要消費的 binlog 文件已經(jīng)被 purge 掉了或者舊位點對應的文件已經(jīng)不存在而你能夠接受“不追歷史數(shù)據(jù)從現(xiàn)在開始同步”的情況。操作步驟如下停止 Canal 實例。備份并刪除或重命名meta.dat文件。編輯instance.properties把位點相關配置調(diào)整為從當前 binlog 起點開始。例如先在 MySQL 上確認當前 binlog 狀態(tài)SHOW MASTER STATUS;假設輸出為File Position mysql-bin.000150 4那么instance.properties中做如下調(diào)整canal.instance.master.journal.namemysql-bin.000150 canal.instance.master.position4 canal.instance.master.timestamp canal.instance.master.gtid如果你的場景允許“不指定具體文件”也可以把journal.name留空并保持canal.instance.master.auto.positiontrue讓 Canal 自動定位到當前 binlog。然后重啟 Canal。啟動日志里如果出現(xiàn)類似這樣的內(nèi)容說明位點已經(jīng)生效INFO ... start successful INFO ... binlogPosition: mysql-bin.000150:4這個方案的優(yōu)點是快、簡單、可操作性強。缺點也很明顯如果你下游是一個需要全量數(shù)據(jù)重建的系統(tǒng)從當前 binlog 起點開始意味著歷史上已經(jīng)產(chǎn)生的數(shù)據(jù)變更不會被同步。所以這個方案通常要和“先做全量同步再啟動增量同步”搭配使用。4.2 方案B修復或重建binlog index文件如果你的實際情況是binlog 文件明明還在磁盤上但binlog.index文件壞了、空了或者記錄不全那就需要用方案 B。在動手前一定要先確認實際文件情況# 查看 datadir 下所有 binlog 文件 ls -lh /data/mysql/lib/mysql/mysql-bin.*然后和 index 文件對比cat /data/mysql/lib/mysql/binlog.index如果文件存在但 index 缺失可以手動重建。步驟如下停掉 MySQL 實例這一步很重要避免運行中的 MySQL 覆蓋 index 文件備份原始 index 文件生成新的 index 文件將現(xiàn)有 binlog 文件的完整路徑按順序?qū)懭胄薷奈募僦骱蜋嘞薮_保 MySQL 進程可讀啟動 MySQL驗證SHOW BINARY LOGS輸出正常。生成 index 文件時可以直接用命令ls -1 /data/mysql/lib/mysql/mysql-bin.* /data/mysql/lib/mysql/binlog.index注意ls -1輸出的是文件名列表如果 binlog 文件路徑帶有目錄需要在輸出時補全路徑。另外如果列表中包含了類似mysql-bin.index這類非 binlog 文件要過濾掉。我個人的建議是能用 MySQL 自帶機制解決就不要手動重建 index 文件。比如如果你的 binlog 文件都還在只是 index 文件丟了可以在停庫后把現(xiàn)有 binlog 文件按名稱排序逐一flush logs不行flush logs需要 MySQL 運行。手動重建是可行方案但要格外小心。更穩(wěn)妥的做法是先備份現(xiàn)有 binlog 文件然后嘗試用 MySQL 的PURGE BINARY LOGS配合TO參數(shù)把過期文件清理掉讓 MySQL 自己維護 index 文件的一致性。當然如果 index 文件已經(jīng)損壞到 MySQL 無法識別就只能走手動修復路線。4.3 方案C用timestamp或GTID方式繞過文件定位如果你不想手動指定journalName position也不想刪除meta.dat還有第三條路改用 timestamp 或 GTID 方式讓 Canal 定位。使用 timestamp 方式時instance.properties中配置canal.instance.master.journal.name canal.instance.master.position canal.instance.master.timestamp1700000000這個時間戳要填你希望開始消費的時間點。Canal 會去尋找第一個發(fā)生在該時間戳之后的事件并自動確定對應的 binlog 文件和偏移量。這里有一個前提MySQL 的 binlog 文件必須還保留著那個時間點附近的事件。如果該時間點對應的 binlog 文件已經(jīng)被清理timestamp 方式依然會失敗。所以這本質(zhì)上是把“文件名定位”換成了“時間定位”并沒有繞開“binlog 文件必須保留得足夠久”這個基本約束。GTID 方式類似。當 MySQL 開啟了 GTID你可以在配置里指定從某個 GTID 開始消費canal.instance.master.gtid3a4f1b2c-aa12-4b5c-9d0e-123456789abc:1-100Canal 會基于 GTID 集合計算出需要拉取的 binlog 區(qū)間。GTID 的好處是天然冪等重復消費可以通過 GTID 集合去重業(yè)務側更安心。缺點是需要你理解 GTID 的語義對于沒接觸過 GTID 的同學來說配置本身就容易寫錯。從我個人的實戰(zhàn)經(jīng)驗看修復這個報錯的最優(yōu)解是優(yōu)先看 binlog 文件的保留情況和meta.dat的位點然后方案 A 兜底方案 C 做特殊場景補充。方案 B 只在 binlog.index 本身損壞時使用別輕易在生產(chǎn)環(huán)境手動重建 index 文件。4.4 各種方案生效后的驗證標準修復完成后不能只看“Canal 進程還活著”就收工。我一般按下面三步做驗證看 Canal 啟動日志確認binlogPosition或者gtid已經(jīng)按預期設置沒有報錯看 MySQL 側連接狀態(tài)SHOW PROCESSLIST;正常能看到 Canal 賬號對應的連接Command為Binlog Dump。如果能看到說明 Canal 已經(jīng)成功向 MySQL 注冊了復制流??聪M端數(shù)據(jù)在源庫執(zhí)行一條簡單的增刪改語句觀察下游 MQ 或目標庫是否在幾秒內(nèi)收到對應的數(shù)據(jù)變更事件。這三個驗證步驟前兩個缺一不可。第三個需要和下游的消費邏輯配合如果下游剛好斷連偶爾會出現(xiàn)數(shù)據(jù)延遲不代表 Canal 沒修好。你可以通過 Canal 自帶的 metrics如果是 Canal Admin 部署或者日志中的table filter調(diào)試輸出進一步確認。5. 這類問題的典型變體與日常預防5.1 幾個容易踩的“變體坑”同樣的底層原因因為觸發(fā)方式不同會表現(xiàn)出不一樣的報錯或現(xiàn)象。遇到Could not find first log file name的同學往往在修好之后還會遇到下面這幾個變體第一個變體binlog 文件沒有消失只是 Canal 去找了一個“未來”的文件。比如配置里寫的是mysql-bin.000200但 MySQL 當前最多才寫到mysql-bin.000180。這種通常是把配置從另一套環(huán)境復制過來沒改位點?,F(xiàn)象一模一樣排查方法也類似。第二個變體Canal 實例目錄被復制到新機器meta.dat里的位點是源機器的。新機器的 binlog 文件序列完全不一樣自然找不到。這種場景下遷移 Canal 時一定要把位點同步重置而不是簡單拷貝目錄。第三個變體Canal 配置里用了相對路徑或自定義路徑的 index 文件。Canal 在解析 index 文件時如果配置里指定的binlogIndexFile路徑不對它會在錯誤的路上去找文件表現(xiàn)為找不到或者解析為空。這種情況雖然少見但一旦發(fā)生排查方向會走很多彎路。第四個變體binlog 文件名帶了奇怪的字符。因為某些自動化腳本把mysql-bin.000126寫成了mysql-bin.000126末尾多空格Canal 匹配時也沒能匹配上。肉眼幾乎看不出來但cat時注意觀察或者在代碼里 print 一下文件名就能發(fā)現(xiàn)。5.2 位點健康監(jiān)控與變更流程紅線修復過一次這種問題之后更應該做的是防止再次發(fā)生。我梳理了幾條我認為值得固化為團隊規(guī)范的“紅線”。第一purge binlog 之前必須先和 Canal 方確認位點。團隊里如果有人動 MySQL 的 binlog 清理策略建議先查一下 Canal 的位點離當前位點有多遠。Canal 的位點可以從meta.dat里獲取也可以從 Canal 的日志或監(jiān)控中看到。如果 Canal 位點滯后太久先處理滯后問題再清理 binlog。第二設置合理的 binlog 保留時間。binlog_expire_logs_seconds不是越大越好也不是越小越好。要結合 Canal 下游的消費速度、以及業(yè)務是否有回溯需求來定。我見過一些團隊把保留時間設為 3 天結果下游 MQ 積壓超過 3 天Canal 直接掛。后來改成 7 天配合磁盤容量監(jiān)控這個問題才消停。第三Canal 位點監(jiān)控要加入告警。最簡單的方式是使用 Canal 提供的 metrics 接口或者寫一個定時腳本定期讀取 Canal 的位點和 MySQL 的SHOW MASTER STATUS計算兩者之間的差值超過閾值就告警。這個差值本質(zhì)上就是“消費落后程度”它比單純監(jiān)控 Canal 是否存活要有意義得多。第四避免手動刪除 binlog 文件。無論出于什么原因不要直接rmbinlog。正確做法是PURGE BINARY LOGS TO mysql-bin.000XXX;或PURGE BINARY LOGS BEFORE YYYY-MM-DD HH:MM:SS;讓 MySQL 自己維護 index 文件的一致性。5.3 我的個人經(jīng)驗與最后建議說說我自己的習慣。踩過這個坑之后我在每一次部署 Canal 時都會做三件事第一件事把meta.dat和instance.properties的位點關系搞清楚再動手。我甚至會在啟動 Canal 之前主動檢查一遍meta.dat的內(nèi)容確認它是空文件或符合預期的位點避免舊狀態(tài)污染新配置。第二件事永遠準備一個“緊急重置腳本”。里面包含停止 Canal、備份meta.dat、重置instance.properties位點、重啟四個步驟。遇到類似問題時直接執(zhí)行腳本能省下很多在 console 上敲命令的時間。第三件事把 binlog 文件的保留策略和 Canal 位點的健康狀況做成一張看板。這張看板不一定非要用多復雜的系統(tǒng)一個定時任務加上一個簡單的表格就夠了。重點是讓“位點落后”這件事在變成故障之前就被發(fā)現(xiàn)。最后如果這次報錯讓你不得不重置了 Canal 位點我建議你花點時間評估一下下游系統(tǒng)的數(shù)據(jù)一致性。尤其是當數(shù)據(jù)變更同時流向了多個目標比如消息隊列和搜索集群重置位點之后歷史數(shù)據(jù)和處理邏輯可能對不上。必要時配合一次全量數(shù)據(jù)校驗總比線上出了臟數(shù)據(jù)再返工要好。Canal 這個組件本身不復雜但它卡在“數(shù)據(jù)庫和業(yè)務系統(tǒng)”之間一旦出問題影響的往往是整條數(shù)據(jù)鏈。把這類報錯的原理和修復方式吃透你后面維護任何基于 binlog 的數(shù)據(jù)同步鏈路都會輕松不少。