Binlog分析利器-binlog_summary.py

​Binlog中,除了具體的SQL,其實,還包含了不少有價值的信息,如,python

  1. 事務的開始時間。
  2. 事務的結束時間。
  3. 事務的開始位置點。
  4. 事務的結束位置點。
  5. 操做的開始時間(一個事務一般會包含多個操做)。
  6. 表的操做信息,如哪些表執行了哪些操做。

拿到上面這些信息,咱們能夠作哪些事情呢?mysql

  1. 基於事務的開始位置點和結束位置點,咱們能夠獲得事務的大小。知道了事務的大小,可用來判斷它是否爲大事務,是不是致使主從延遲的緣由。
  2. 基於事務的開始時間和結束時間,咱們能夠獲得事務的持續時間。
  3. 經過分析表的操做信息,可間接定位出線上的熱點表。

開發了一個簡單的Binlog分析工具-binlog_summary.py,可提取上面這些信息,並在此基礎上,進行一些常見分析。git

1. 下載地址

https://github.com/slowtech/dba-toolkit/blob/master/MySQL/binlog_summary.pygithub

 

2. 參數解析

# python binlog_summary.py --help
usage: binlog_summary.py [-h] [-f BINLOG_TEXT_FILE] [--new]
                         [-c {tps,opr,transaction}] [--start START_DATETIME]
                         [--stop STOP_DATETIME] [--sort SORT_CONDITION] [-e]
                         [--limit LIMIT]

optional arguments:
  -h, --help            show this help message and exit
  -f BINLOG_TEXT_FILE, --file BINLOG_TEXT_FILE
                        Binlog text file, not the Raw binary file
  --new                 Make a fresh start
  -c {tps,opr,transaction}, --command {tps,opr,transaction}
                        Command type: [tps, opr, transaction],tps: transaction
                        per second, opr: dml per table, transaction: show
                        transaction info
  --start START_DATETIME
                        Start datetime, for example: 2004-12-25 11:25:56
  --stop STOP_DATETIME  Stop datetime, for example: 2004-12-25 11:25:56
  --sort SORT_CONDITION
                        Sort condition: time or size, you can use it when
                        command type is transaction
  -e, --extend          Show transaction info in detail,you can use it when
                        command type is transaction
  --limit LIMIT         Limit the number of rows to display

其中,sql

  • -f:Binlog經過mysqlbinlog解析後的文本文件。注意,是文本文件,不是Binlog原始文件。使用mysqlbinlog解析時,建議指定-v(顯示Pseudo SQL,即僞SQL)和--base64-output=decode-rows(不會顯示Base64的編碼結果)這兩個參數,這樣,生成的文本文件纔是最小的,相應地,binlog_summary.py解析起來也是最快的。具體命令以下:數據庫

    # mysqlbinlog --base64-output=decode-rows -v mysql-bin.000001 > /tmp/mysql-bin.000001.txt
  • --new:工具的分析結果默認是存儲在sqlite3數據庫中。若是指定了--new,會刪除以前建立的sqlite3數據庫。注意,在對一個新的Binlog進行分析時需指定該參數。編輯器

  • -c:指定命令的類型。支持的命令類型有:工具

    • tps:分析實例的TPS信息。
    • opr:分析表的操做狀況。
    • transaction:分析事務信息。
  • --start:開始時間。分析指定時間段的日誌。測試

  • --stop:結束時間。this

  • --sort:排序條件。當命令類型是transaction時,默認是按照事務的執行順序輸出的,可指定size,按事務大小排序,也可指定time,按事務的持續時間排序。

  • -e:當命令類型是transaction時,指定該參數會輸出每一個事務的詳細操做信息。

  • --limit:限制輸出的行數。

 

3. 常見用法

3.1 分析實例的TPS信息

# python binlog_summary.py -f /tmp/mysql-bin.000001.txt -c tps --limit 5
COMMIT_TIME        TPS                
2021-04-17 08:12:14 1                  
2021-04-17 08:12:15 7                  
2021-04-17 08:12:16 12                 
2021-04-17 08:12:17 12                 
2021-04-17 08:12:18 9             

注意,這裏的TPS是基於事務的提交時間來統計的。

如此細粒度的TPS信息,只能經過Binlog來獲取。通常的監控很難作到這一點。

若是要對TPS進行排序,可經過管道 + sort,如,

# python binlog_summary.py -f /tmp/mysql-bin.000001.txt -c tps | sort -k 3 -n 

其中,-k 3是對第三列進行排序,-n是按照數值(默認是字符)的大小進行排序,也可指定-r參數,反向排序。

 

3.2 分析表的操做狀況

# python binlog_summary.py -f /tmp/mysql-bin.000001.txt -c opr --limit 5
TABLE_NAME         DML_TYPE           NUMS               
sbtest.sbtest4     INSERT             609526             
sbtest.sbtest6     INSERT             543658             
sbtest.sbtest2     INSERT             309701             
sbtest.sbtest7     INSERT             309651             
sbtest.sbtest5     INSERT             309606         

這裏的NUMS是執行次數。

 

4.3 分析Binlog中最大的5個事務

# python binlog_summary.py -f /tmp/mysql-bin.000001.txt -c transaction --sort size --limit 5
TRANS_NAME BEGIN_TIME          COMMIT_TIME         BEGIN_LOG_POS  COMMIT_LOG_POS DURATION_TIME  SIZE           
t62562     2021-04-17 08:30:01 2021-04-17 08:32:31 734265229      867878401      150            133613172      
t62561     2021-04-17 08:29:19 2021-04-17 08:29:19 677048698      734265148      0              57216450       
t62563     2021-04-17 08:33:26 2021-04-17 08:33:50 867878482      925094932      24             57216450       
t62564     2021-04-17 08:34:21 2021-04-17 08:34:21 925095013      971504525      0              46409512       
t62565     2021-04-17 08:34:58 2021-04-17 08:34:58 971504606      1016178117     0              44673511    

其中,

  • TRANS_NAME:事務編號。
  • BEGIN_TIME:事務開始時間。
  • COMMIT_TIME:事務提交時間。
  • BEGIN_LOG_POS:事務的開始位置點。
  • COMMIT_LOG_POS:事務的結束位置點。
  • DURATION_TIME:事務的持續時間,單位秒。其中,DURATION_TIME = COMMIT_TIME - BEGIN_TIME。
  • SIZE:事務的大小,單位字節,其中,SIZE = COMMIT_LOG_POS - BEGIN_LOG_POS。

拿到事務的大小,咱們能夠粗略地判斷這個Binlog中是否存在大事務。若是要進一步分析事務中包含哪些操做,需加上--extend,如,

# python binlog_summary.py -f /tmp/mysql-bin.000001.txt -c transaction --sort size --extend --limit 5
TRANS_NAME BEGIN_TIME           COMMIT_TIME          BEGIN_LOG_POS  COMMIT_LOG_POS  DURATION_TIME SIZE
t62562     2021-04-17 08:30:01  2021-04-17 08:32:31  734265229      867878401       150           133613172
├──        sbtest.sbtest2                            DELETE         200000
├──        sbtest.sbtest3                            UPDATE         100000
├──        sbtest.sbtest4                            INSERT         300000
t62561     2021-04-17 08:29:19  2021-04-17 08:29:19  677048698      734265148       0             57216450
├──        sbtest.sbtest1                            DELETE         300000
t62563     2021-04-17 08:33:26  2021-04-17 08:33:50  867878482      925094932       24            57216450
├──        sbtest.sbtest6                            DELETE         300000
t62564     2021-04-17 08:34:21  2021-04-17 08:34:21  925095013      971504525       0             46409512
├──        sbtest.sbtest5                            UPDATE         121324
t62565     2021-04-17 08:34:58  2021-04-17 08:34:58  971504606      1016178117      0             44673511
├──        sbtest.sbtest6                            INSERT         234234

 

4. 實現思路

binlog_summary.py是分析Binlog通過mysqlbinlog解析後的文本文件。具體來講,

  1. 逐行分析解析後的文本。

    爲了保證分析的高效,只會分析含有如下關鍵詞的行,其它行則直接跳過。

    match_sub_strings=["use", "# at", "server id", "BEGIN", "insert", "delete", "update", "DELETE", "INSERT", "UPDATE","COMMIT"]
    if not any(each_str in line for each_str in match_sub_strings):
        continue
  2. 分析後的基礎數據,會存在sqlite3數據庫中。爲何要這麼設計呢?

    • 基礎數據可重複使用。畢竟binlog_summary.py支持多種維度的分析,若是每進行一次分析,都要從新解析一次文本,不夠高效也不必。
    • sqlite3支持SQL。簡單的分組聚合仍是用SQL比較方便,並且,sqlite3自己就足夠輕量級,無需安裝部署。同時,Python中經過sqlite3庫就可直接操做。

接下來,再來講說,爲何是分析Binlog通過mysqlbinlog解析後的文本文件,而不是基於MySQL複製協議,直接分析Binlog呢?基於MySQL複製協議,這種方式有個弊端,就是通用性不夠,每出一個新的版本,都要進行相應的適配。

基於文原本分析,不少人可能會以爲不高效。

實際測試了下,分析一個1G的Binlog,大概3min,也不算慢。

# time mysqlbinlog --base64-output=decode-rows -v mysql-bin.000001 > /tmp/mysql-bin.000001.txt

real    0m28.148s
user    0m13.821s
sys     0m2.588s

# time python binlog_summary.py -f /tmp/mysql-bin.000001.txt --new -c tps --limit 1 
COMMIT_TIME        TPS                
2021-04-17 08:12:14 1                                  

real    2m31.682s
user    2m2.253s
sys     0m2.269s
相關文章
相關標籤/搜索