做者:高鵬(八怪)
文章末尾有他著做的《深刻理解 MySQL 主從原理 32 講》,深刻透徹理解 MySQL 主從,GTID 相關技術知識。
有了前面對 Event 的瞭解,咱們就能夠利用這些 Event 來完成一些工做了。我曾經在學習了這些經常使用的 Event 後,使用 C 語言寫過一個解析 Event 的工具,我叫它‘infobin’,意思就是從 binary log 提取信息的意思。據我所知雖然這個工具在少數狀況下會出現 BUG 可是仍是有些朋友在用。我這裏並非要推廣個人工具,而是要告訴你們這種思路。我是結合工做中遇到的一些問題來完成了這個工具的,主要功能包含以下:python
下面是這個工具的地址,供你們參考:
https://github.com/gaopengcar...
這個工具的幫助信息以下:mysql
[root@gp1 infobin]# ./infobin USAGE ERROR! [Author]: gaopeng [QQ]:22389860[blog]:http://blog.itpub.net/7728585/ --USAGE:./infobin binlogfile pieces bigtrxsize bigtrxtime [-t] [-force] [binlogfile]:binlog file! [piece]:how many piece will split,is a Highly balanced histogram, find which time generate biggest binlog.(must:piece<2000000) [bigtrxsize](bytes):larger than this size trx will view.(must:trx>256(bytes)) [bigtrxtime](sec):larger than this sec trx will view.(must:>0(sec)) [[-t]]:if[-t] no detail isprintout,the result will small [[-force]]:force analyze if unkown error check!!
接下來咱們具體來看看這幾個功能大概是怎麼實現的。git
前面我已經屢次提到過對於一個手動提交的事務而言有以下特色,咱們以‘Insert’語句爲列:github
那實際上咱們就能夠用(1)減去(2)就能獲得第一個‘DML’命令發起到‘COMMIT’命令發起之間所消耗的時間,再使用一個用戶輸入參數來自定義多久沒有提交的事務叫作長期未提交的事務就能夠了,個人工具中使用 bigtrxtime 做爲這個輸入。咱們來用一個例子說明,咱們作以下語句:sql
咱們來看看 Event 的順序和時間以下:shell
若是咱們使用最後一個 XID_EVENT 的時間減去 QUERY_EVENT 的時間,那麼這個事務從第一條語句開始到‘COMMIT’的時間就計算出來了。注意一點,實際上‘BEGIN’命令並無記錄到 Event 中,它只是作了一個標記讓事務不會自動進入提交流程。數據庫
關於‘BEGIN’命令作了什麼能夠參考個人簡書文章以下:
https://www.jianshu.com/p/6de...
這部分實現比較簡單,咱們只須要掃描每個事務 GTID_LOG_EVENT 和 XID_EVENT 之間的全部 Event 將它們的總和計算下來,就能夠獲得每個事務生成 Event 的大小(可是爲了兼容最好計算 QUERY_EVENT 和 XID_EVENT 之間的 Event 總量)。再使用一個用戶輸入參數自定義多大的事務叫作大事務就能夠了,個人工具中使用 bigtrxsize 做爲這個輸入參數。
若是參數 binlog_row_image 參數設置爲‘FULL’,咱們能夠大概計算一下特定表的每行數據修改生成的日誌佔用的大小:工具
我認爲 20M 做爲大事務的定義比較合適,固然這個根據本身的需求進行計算。學習
這個實現就很簡單了,咱們只須要把 binary log 按照輸入參數進行分片,統計結束 Event 和開始 Event 的時間差值就能大概算出每一個分片生成花費了多久時間,咱們工具使用 piece 做爲分片的傳入參數。
經過這個分析,咱們能夠大概知道哪一段時間 Event 生成量更大,也側面反映了數據庫的繁忙程度。this
這個功能也很是實用,經過這個分析咱們能夠知道數據庫中哪個表的修改量最大。實現方式主要是經過掃描 binary log 中的 MAP_EVENT 和接下來的 DML Event,經過 table id 獲取表名,而後將 DML Event 的大小納入這個表中,作一個鏈表,最後排序輸出就行了。
可是前面咱們說過 table id 即使在一個事務中也可能改變,這是我開始沒有考慮到的,所以這個工具備必定的問題,可是大部分狀況是能夠正常運行的。
下面我就來展現一下我說的這些功能,我作了以下操做:
mysql> flush binary logs; Query OK, 0 rows affected (0.51 sec) mysql> select count(*) from tti; +----------+ | count(*) | +----------+ | 98304| +----------+ 1 row inset(0.06 sec) mysql> deletefrom tti; Query OK, 98304 rows affected (2.47 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> insert into tti values(1,'gaopeng'); Query OK, 1 row affected (0.00 sec) mysql> select sleep(20); +-----------+ | sleep(20) | +-----------+ | 0| +-----------+ 1 row inset(20.03 sec) mysql> commit; Query OK, 0 rows affected (0.22 sec) mysql> insert into tpp values(10); Query OK, 1 row affected (0.14 sec)
在示例中我切換了一個 binary log,同時作了 3 個事務:
咱們使用工具來分析一下,下面是統計輸出:
./infobin mysql-bin.0000053100000015-t > log.log more log.log ... -------------Total now-------------- Trx total[counts]:3 Event total[counts]:125 Max trx event size:8207(bytes) Pos:420[0X1A4] Avg binlog size(/sec):9265.844(bytes)[9.049(kb)] Avg binlog size(/min):555950.625(bytes)[542.921(kb)] --Piece view: (1)Time:1561442359-1561442383(24(s)) piece:296507(bytes)[289.558(kb)] (2)Time:1561442383-1561442383(0(s)) piece:296507(bytes)[289.558(kb)] (3)Time:1561442383-1561442455(72(s)) piece:296507(bytes)[289.558(kb)] --Large than 500000(bytes) trx: (1)Trx_size:888703(bytes)[867.874(kb)] trx_begin_p:299[0X12B] trx_end_p:889002[0XD90AA] Total large trx count size(kb):#867.874(kb) --Large than 15(secs) trx: (1)Trx_sec:31(sec) trx_begin_time:[2019062514:00:08(CST)] trx_end_time:[2019062514:00:39(CST)] trx_begin_pos:889067 trx_end_pos:889267 query_exe_time:0 --EveryTable binlog size(bytes) and times: Note:size unit is bytes ---(1)CurrentTable:test.tpp:: Insert:binlog size(40(Bytes)) times(1) Update:binlog size(0(Bytes)) times(0) Delete:binlog size(0(Bytes)) times(0) Total:binlog size(40(Bytes)) times(1) ---(2)CurrentTable:test.tti:: Insert:binlog size(48(Bytes)) times(1) Update:binlog size(0(Bytes)) times(0) Delete:binlog size(888551(Bytes)) times(109) Total:binlog size(888599(Bytes)) times(110) ---Total binlog dml event size:888639(Bytes) times(111)
咱們發現咱們作的操做都統計出來了:
--Large than 500000(bytes) trx: (1)Trx_size:888703(bytes)[867.874(kb)] trx_begin_p:299[0X12B] trx_end_p:889002[0XD90AA]
--Large than 15(secs) trx: (1)Trx_sec:31(sec) trx_begin_time:[2019062514:00:08(CST)] trx_end_time:[2019062514:00:39(CST)] trx_begin_pos:889067 trx_end_pos:889267 query_exe_time:0
--EveryTable binlog size(bytes) and times: Note:size unit is bytes ---(1)CurrentTable:test.tpp:: Insert:binlog size(40(Bytes)) times(1) Update:binlog size(0(Bytes)) times(0) Delete:binlog size(0(Bytes)) times(0) Total:binlog size(40(Bytes)) times(1) ---(2)CurrentTable:test.tti:: Insert:binlog size(48(Bytes)) times(1) Update:binlog size(0(Bytes)) times(0) Delete:binlog size(888551(Bytes)) times(109) Total:binlog size(888599(Bytes)) times(110) ---Total binlog dml event size:888639(Bytes) times(111)
好了到這裏我想告訴你的就是,學習了 Event 事後就能夠本身經過各類語言去試着解析 binary log,也許你還能寫出更好的工具實現更多的功能。
固然也能夠經過 mysqlbinlog 進行解析後,而後經過 shell/python 去統計,可是這個工具的速度要遠遠快於這種方式。
最後推薦高鵬的專欄《深刻理解 MySQL 主從原理 32 講》,想要透徹瞭解學習 MySQL 主從原理的朋友不容錯過。