Binlog中,除了具體的SQL,其實,還包含了不少有價值的信息,如,python
拿到上面這些信息,咱們能夠作哪些事情呢?mysql
開發了一個簡單的Binlog分析工具-binlog_summary.py,可提取上面這些信息,並在此基礎上,進行一些常見分析。git
https://github.com/slowtech/dba-toolkit/blob/master/MySQL/binlog_summary.pygithub
# 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:指定命令的類型。支持的命令類型有:工具
--start:開始時間。分析指定時間段的日誌。測試
--stop:結束時間。this
--sort:排序條件。當命令類型是transaction時,默認是按照事務的執行順序輸出的,可指定size,按事務大小排序,也可指定time,按事務的持續時間排序。
-e:當命令類型是transaction時,指定該參數會輸出每一個事務的詳細操做信息。
--limit:限制輸出的行數。
# 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參數,反向排序。
# 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是執行次數。
# 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
其中,
拿到事務的大小,咱們能夠粗略地判斷這個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
binlog_summary.py是分析Binlog通過mysqlbinlog解析後的文本文件。具體來講,
逐行分析解析後的文本。
爲了保證分析的高效,只會分析含有如下關鍵詞的行,其它行則直接跳過。
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
分析後的基礎數據,會存在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