共计 2957 个字符,预计需要花费 8 分钟才能阅读完成。
相信大家都了解 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 版本的其他功能都有人提到了,这个没人提到,我也简单的介绍一下,哈哈。
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='linuxidc'; | |
Query OK, 1 row affected (0.03 sec) | |
Rows matched: 1 Changed: 1 Warnings: 0 | |
mysql> |
解析 binlog 看看啥情况
[root@linuxidc 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='linuxidc' /* 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='linuxidc' /* 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@linuxidc 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='linuxidc'; | |
Query OK, 1 row affected (0.02 sec) | |
Rows matched: 1 Changed: 1 Warnings: 0 | |
mysql> |
再解析 binlog 看看啥情况:
[root@linuxidc 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@linuxidc 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,支持函数索引(通过虚拟列实现),支持只读事务等等等。
本文永久更新链接地址 :http://www.linuxidc.com/Linux/2016-12/138158.htm
