使用過mysql的binlog嗎?看看如何用binlog排查阿里開源項目otter的問題


MySQL的binlog相信大家都有所耳聞,但是可能沒有真正日常使用過。

因此,本文結合一個otter小坑的排查案例,來分享下binlog的日常使用方式。


重點了解下:

  • binlog的導出方式

  • binlog的解析方式

  • 結合案例分享下開源項目otter的一個小坑

1.案例背景

某個週末突然收到報警,發現線上多雲數據庫的數據同步任務掛起,顯示日誌寫入數據失敗。


錯誤原因非常明顯:

唯一索引衝突。

查看了一下源庫的數據內容,確實已經update完畢。而目標庫的數據內容,確實存在衝突導致無法update。

2.排查過程

這個數據同步任務,使用了阿里開源的數據庫同步項目otter。難道遇到了什麼bug?

otter項目是阿里巴巴開源的數據庫同步系統。

基於數據庫增量日誌解析,準實時同步到本機房或異地機房的mysql/oracle數據庫的一個分佈式數據庫同步系統。

直接開始排查問題。

2.1 表結構是否一致

爲什麼源庫沒有衝突,目標庫會有衝突呢?是不是表結構不一致?或者是源庫發生了表結構變更沒有同步到目標庫?

確認了下源庫的表結構和目標庫表結構是一致的,且都有對應的唯一索引udx_position。

2.2 排查源庫binlog

那源庫到底是怎麼更新成功的?只能撈一下binlog了。

首先導出線上正在使用的binlog文件。

在數據庫上執行

flush logs

這個命令會關閉當前正在寫入的binlog文件,然後生成一個序號加1的新的binlog文件讓mysql server繼續使用。

等待幾分鐘,讓當前的binlog落盤爲日誌文件,本案例中爲xxxx_binlog_mysqlbin.000005。

然後下載到本地。


通過mysqlbinlog命令解析,輸出爲指定文件xxx.binlog,如下:

mysqlbinlog  --start-datetime='2020-11-20 18:17:00' --stop-datetime='2020-11-20 18:21:01' --base64-output=decode-rows -v -d db xxxx_binlog_mysqlbin.000005 > xxx.binlog
  • binlog格式binlog_format採用row模式。僅保存記錄被修改細節,不記錄sql語句上下文相關信息優點:能非常清晰的記錄下每行數據的修改細節,不需要記錄上下文相關信息,因此不會發生某些特定情況下的procedure、function、及trigger的調用觸發無法被正確複製的問題,任何情況都可以被複制,且能加快從庫重放日誌的效率,保證從庫數據的一致性。

  • 通過 --start-datatime和--stop-datetime指定解析的起止時間

  • row模式生成的sql編碼需要解碼,不能用常規的辦法去生成,需要加上相應的參數(--base64-output=decode-rows -v)才能顯示出sql語句


binlog的內容解析後sql的過程如下(爲了更好地看清過程,這裏不展示binlog原文,而是一個邏輯過程):


我們能清楚地看到,源庫通過一個事務中,交換position(唯一索引的列)的值,達到更新唯一索引而不造成衝突的目的。

那目標庫爲什麼會衝突呢?


2.3 查看目標庫的sql審計

由於數據同步失敗掛起,所以目標庫的同步數據暫時不會寫入對應的binlog記錄。

因此,我們需要通過sql審計來查看目標庫的寫入情況。

這裏同樣展示sql審計中撈出的相關過程:

Oh~ My~ God!

事務中間的update交換過程居然被合併了!!

所以造成了唯一索引衝突,更新失敗。


3.求證

重新去翻了一遍otter的wiki,看到了關於《otter數據入庫算法》說明。

https://github.com/alibaba/otter/wiki/Otter%E6%95%B0%E6%8D%AE%E5%85%A5%E5%BA%93%E7%AE%97%E6%B3%95


確實存在操作合併的情況。

這樣做許多好處:

  • insert/行記錄update 執行merge sql,解決重複數據執行

  • 合併算法執行後,單pk主鍵只有一條記錄,減少並行load算法的複雜性(比如batch合併,並行/串行等處理)

  • 同步速度相比於mysql的複製,拋棄了強一致性,約有5倍左右的性能提升

找了下源碼,定位到DbLoadAction類


令人遺憾的是,我們發現竟然沒有開關可以控制。

4.解決方案。

到上面基本已經水落石出,找到了問題的根本原因。由於otter對事務內的update操作進行了合併,導致了目標庫唯一索引衝突。

那怎麼解決呢?

看到文檔上有這麼一句話


那麼,對應到這個案例,或者說其他唯一索引的變更,只能通過 先刪除,再插入,而不是通過update進行交換


所以,如何使用binlog來排查問題,你學了嗎?:)




往期熱門筆記合集推薦:


原創:阿丸筆記(微信公衆號:aone_note),歡迎 分享,轉載請保留出處。

掃描下方二維碼可以關注我哦~

                                                                              覺得不錯,就點個  再看 吧👇



本文分享自微信公衆號 - 阿丸筆記(aone_note)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章