相信大家都了解mysql binlog的格式,那就是有三種,分別是STATEMENT,MiXED,ROW。各有優劣,具體的請大家自行查閱資料。在MySQL 5.7版本以前,雖然ROW格式有各種各樣的好處。
1. 比如加快從庫重放日志;ROW直接調用mysql的存儲引擎接口(handler API) 來執行行的插入、刪除和更新,完全跳過了mysql的優化器的處理邏輯。
2. 保證主從數據的一致性。記錄的每一行的變更。
3. 可以通過對binlog的逆向解析實現閃回功能。
那么實際上還是有一個缺陷,那就是由於記錄的是每一行的變更,會帶來磁盤IO上的開銷,同時由於binlog日志變大,網絡開銷也變大了。那么在MySQL 5.7以后binlog的格式默認就是ROW了,同時引入了新的參數binlog_row_image,這個參數默認值是FULL,其還有一個值是minimal。由於5.7版本的其他功能都有人提到了,這個沒人提到,我也簡單的介紹一下,哈哈。(后面發現5.6就有該參數了,關注度不夠,該死。。)
FULL記錄每一行的變更,minimal只記錄影響后的行。下面簡單的測試一下大家就明白了。
mysql> show variables like '%row_im%'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | binlog_row_image | FULL | +------------------+-------+ 1 row in set (0.01 sec) mysql> update t2 set uid=99 where name='yayundeng'; Query OK, 1 row affected (0.03 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql>
解析binlog看看啥情況
[root@yayundeng 3306]# mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS mysql-bin.000010 | tail -n 20 #161210 11:02:32 server id 152 end_log_pos 2043 CRC32 0x3ce8a225 Update_rows: table id 110 flags: STMT_END_F ### UPDATE `test`.`t2` ### WHERE ### @1=1 /* INT meta=0 nullable=0 is_null=0 */ ### @2='gz' /* STRING(20) meta=65044 nullable=1 is_null=0 */ ### @3='yayundeng' /* STRING(20) meta=65044 nullable=1 is_null=0 */ ### @4=1 /* INT meta=0 nullable=1 is_null=0 */ ### SET ### @1=1 /* INT meta=0 nullable=0 is_null=0 */ ### @2='gz' /* STRING(20) meta=65044 nullable=1 is_null=0 */ ### @3='yayundeng' /* STRING(20) meta=65044 nullable=1 is_null=0 */ ### @4=99 /* INT meta=0 nullable=1 is_null=0 */ # at 2043 #161210 11:02:32 server id 152 end_log_pos 2074 CRC32 0x93619126 Xid = 49 COMMIT/*!*/; SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/; DELIMITER ; # End of log file /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; [root@yayundeng 3306]#
下面設置一下binlog_row_image的值為minimal
mysql> set binlog_row_image ='minimal'; Query OK, 0 rows affected (0.00 sec) mysql> update t2 set uid=100 where name='yayundeng'; Query OK, 1 row affected (0.02 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql>
再解析binlog看看啥情況:
[root@yayundeng 3306]# mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS mysql-bin.000010 | tail -n 20 SET TIMESTAMP=1481339144/*!*/; BEGIN /*!*/; # at 2211 #161210 11:05:44 server id 152 end_log_pos 2263 CRC32 0x57948074 Table_map: `test`.`t2` mapped to number 110 # at 2263 #161210 11:05:44 server id 152 end_log_pos 2309 CRC32 0x72114b1f Update_rows: table id 110 flags: STMT_END_F ### UPDATE `test`.`t2` ### WHERE ### @1=1 /* INT meta=0 nullable=0 is_null=0 */ ### SET ### @4=100 /* INT meta=0 nullable=1 is_null=0 */ # at 2309 #161210 11:05:44 server id 152 end_log_pos 2340 CRC32 0x23e45a71 Xid = 52 COMMIT/*!*/; SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/; DELIMITER ; # End of log file /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; [root@yayundeng 3306]#
可以清楚的看到,當把binlog_row_image設置為minimal以后,binlog記錄的就只是影響后的行,大贊。如此一來使用ROW格式一定是首選了,完全沒必要使用STATEMENT,MiXED。不過現在也沒有人使用STATEMENT了,所以准確的說就是完全沒必要使用MiXED格式了。
總結:
MySQL 5.7是真正的一個里程碑的版本,比如可以在線調整bp pool,在線修改復制過濾,真正意義上多線程復制(5.6是基於庫,5.7是基於表),支持bp pool預熱,支持undo log回收,支持通用表空間,支持json,支持函數索引(通過虛擬列實現),支持只讀事務等等等。
