本文主要给大家简单讲讲binlog是如何记录mysql对事务表和非事务表的DML操作,相关专业术语大家可以上网查查或者找一些相关书籍补充一下,这里就不涉猎了,我们就直奔主题吧,希望binlog是如何记录mysql对事务表和非事务表的DML操作这篇文章可以给大家带来一些实际帮助。
实验环境:mysql官方社区版5.7.18, 操作系统centos7.3,binlog日志格式采用row格式。
1、创建Myisam表b和Innodb表a。
CREATE TABLE `a` ( `id` int(11) NOT NULL, `name` varchar(10) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `b` ( `id` int(11) DEFAULT NULL, `name` varchar(10) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
可以看出,两个表结构都是一样的,除了引擎不同。
2、根据GTID是否开启,分为2大类:
(1.1)关闭GTID,显式开启事务并提交事务。
执行的DML操作如下:
root@localhost:mysql3306.sock 16:28: [test]>begin;
Query OK, 0 rows affected (0.00 sec)
root@localhost:mysql3306.sock 16:28: [test]>insert into a values (1,"x");
Query OK, 1 row affected (0.00 sec)
root@localhost:mysql3306.sock 16:29: [test]>insert into b values (1,"x");
Query OK, 1 row affected (0.00 sec)
root@localhost:mysql3306.sock 16:29: [test]>commit;
Query OK, 0 rows affected (0.00 sec)
生成的相应binlog日志如下:
[root@mysql3 binlog]# mysqlbinlog -vv mysql-bin.000001 --base64-output=decode-rows
;
;
DELIMITER ;
# at 4
#180122 16:28:29 server id 43306 end_log_pos 123 CRC32 0x37c1a2aa Start: binlog v 4, server v 5.7.18-log created 180122 16:28:29 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK;
# at 123
#180122 16:28:29 server id 43306 end_log_pos 154 CRC32 0x52be72b2 Previous-GTIDs
# [empty]
# at 154
#180122 16:29:03 server id 43306 end_log_pos 219 CRC32 0x0769b732 Anonymous_GTID last_committed=0 sequence_number=1
SET @@SESSION.GTID_NEXT= 'ANONYMOUS';
# at 219
#180122 16:29:03 server id 43306 end_log_pos 291 CRC32 0x0e3a8a35 Query thread_id=4 exec_time=0 error_code=0
SET TIMESTAMP=1516609743;
SET @@session.pseudo_thread_id=4;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1;
SET @@session.sql_mode=2097152;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33;
SET @@session.lc_time_names=0;
SET @@session.collation_database=DEFAULT;
BEGIN
;
# at 291
#180122 16:29:03 server id 43306 end_log_pos 338 CRC32 0xfe6cd337 Table_map: `test`.`b` mapped to number 222
# at 338
#180122 16:29:03 server id 43306 end_log_pos 380 CRC32 0x0d64e0a4 Write_rows: table id 222 flags: STMT_END_F
### INSERT INTO `test`.`b`
### SET
### @1=1
### @2='x'
# at 380
#180122 16:29:03 server id 43306 end_log_pos 453 CRC32 0xd4cc34e1 Query thread_id=4 exec_time=0 error_code=0
SET TIMESTAMP=1516609743;
COMMIT
;
# at 453
#180122 16:29:05 server id 43306 end_log_pos 518 CRC32 0xeec8cb53 Anonymous_GTID last_committed=1 sequence_number=2
SET @@SESSION.GTID_NEXT= 'ANONYMOUS';
# at 518
#180122 16:29:00 server id 43306 end_log_pos 590 CRC32 0xb472a7d3 Query thread_id=4 exec_time=0 error_code=0
SET TIMESTAMP=1516609740;
BEGIN
;
# at 590
#180122 16:29:00 server id 43306 end_log_pos 637 CRC32 0xe848c910 Table_map: `test`.`a` mapped to number 221
# at 637
#180122 16:29:00 server id 43306 end_log_pos 679 CRC32 0xec326782 Write_rows: table id 221 flags: STMT_END_F
### INSERT INTO `test`.`a`
### SET
### @1=1
### @2='x'
# at 679
#180122 16:29:05 server id 43306 end_log_pos 710 CRC32 0x5b9b8331 Xid = 58
COMMIT;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' ;
DELIMITER ;
# End of log file
;
;
从生成的binlog来看,不管是Myisam还是Innodb引擎,都生成相应的binlog日志。
(1.2)关闭GTID,显式开启事务并回滚事务
执行的DML操作如下:
root@localhost:mysql3306.sock 16:29: [test]>flush logs;
Query OK, 0 rows affected (0.01 sec)
root@localhost:mysql3306.sock 16:35: [test]>begin;
Query OK, 0 rows affected (0.01 sec)
root@localhost:mysql3306.sock 16:35: [test]>insert into a values (2,"x");
Query OK, 1 row affected (0.00 sec)
root@localhost:mysql3306.sock 16:36: [test]>insert into b values (2,"x");
Query OK, 1 row affected (0.00 sec)
root@localhost:mysql3306.sock 16:36: [test]>rollback;
Query OK, 0 rows affected, 1 warning (0.01 sec)
当前表的数据如下:
root@localhost:mysql3306.sock 16:36: [test]>select * from a;
+----+------+
| id | name |
+----+------+
| 1 | x |
+----+------+
1 row in set (0.00 sec)
root@localhost:mysql3306.sock 16:37: [test]>select * from b;
+------+------+
| id | name |
+------+------+
| 1 | x |
| 2 | x |
+------+------+
2 rows in set (0.00 sec)
生成的相应binlog日志如下:
[root@mysql3 binlog]# mysqlbinlog -vv mysql-bin.000002 --base64-output=decode-rows
;
;
DELIMITER ;
# at 4
#180122 16:35:39 server id 43306 end_log_pos 123 CRC32 0xed4918d4 Start: binlog v 4, server v 5.7.18-log created 180122 16:35:39
# Warning: this binlog is either in use or was not closed properly.
# at 123
#180122 16:35:39 server id 43306 end_log_pos 154 CRC32 0x25a5629b Previous-GTIDs
# [empty]
# at 154
#180122 16:36:11 server id 43306 end_log_pos 219 CRC32 0xe56a83ea Anonymous_GTID last_committed=0 sequence_number=1
SET @@SESSION.GTID_NEXT= 'ANONYMOUS';
# at 219
#180122 16:36:11 server id 43306 end_log_pos 291 CRC32 0x322b71cf Query thread_id=4 exec_time=0 error_code=0
SET TIMESTAMP=1516610171;
SET @@session.pseudo_thread_id=4;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1;
SET @@session.sql_mode=2097152;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33;
SET @@session.lc_time_names=0;
SET @@session.collation_database=DEFAULT;
BEGIN
;
# at 291
#180122 16:36:11 server id 43306 end_log_pos 338 CRC32 0xd5964b6b Table_map: `test`.`b` mapped to number 222
# at 338
#180122 16:36:11 server id 43306 end_log_pos 380 CRC32 0xa2b7dc67 Write_rows: table id 222 flags: STMT_END_F
### INSERT INTO `test`.`b`
### SET
### @1=2
### @2='x'
# at 380
#180122 16:36:11 server id 43306 end_log_pos 453 CRC32 0x89983e18 Query thread_id=4 exec_time=0 error_code=0
SET TIMESTAMP=1516610171;
COMMIT
;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' ;
DELIMITER ;
# End of log file
;
;
从生成的binlog可知,表a回滚了数据,而表b由于是非事务表的缘故,没有回滚数据。同时表b的数据变更也生成对应的binlog日志。而表a由于事务回滚的缘故,没有变更数据,也没有生成binlog。
(2.1)开启GTID,显式开启事务并提交事务。
执行的DML操作如下:
root@localhost:mysql3306.sock 16:44: [test]>begin;
Query OK, 0 rows affected (0.00 sec)
root@localhost:mysql3306.sock 16:44: [test]>insert into a values (3,"x");
Query OK, 1 row affected (0.02 sec)
root@localhost:mysql3306.sock 16:44: [test]>insert into b values (3,"x");
ERROR 1785 (HY000): Statement violates GTID consistency: Updates to non-transactional tables can only be done in either autocommitted statements or single-statement transactions, and never in the same statement as updates to transactional tables.
root@localhost:mysql3306.sock 16:44: [test]>commit;
Query OK, 0 rows affected (0.01 sec)
从报错信息可知,在开启GTID模式下,非事务表的DML操作只能在autocommitted statements和single-statement transactions情况下执行,在一个显式事务中混合事务表和非事务表的DML操作是不被允许的。
生成的相应binlog日志如下:
[root@mysql3 binlog]# mysqlbinlog -vv mysql-bin.000001 --base64-output=decode-rows
;
;
DELIMITER ;
# at 4
#180122 16:44:07 server id 43306 end_log_pos 123 CRC32 0xf53a5a98 Start: binlog v 4, server v 5.7.18-log created 180122 16:44:07 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK;
# at 123
#180122 16:44:07 server id 43306 end_log_pos 154 CRC32 0xb9b802e5 Previous-GTIDs
# [empty]
# at 154
#180122 16:44:47 server id 43306 end_log_pos 219 CRC32 0x716ab799 GTID last_committed=0 sequence_number=1
SET @@SESSION.GTID_NEXT= '5252f852-685e-11e7-8eeb-000c299fe44c:1';
# at 219
#180122 16:44:32 server id 43306 end_log_pos 291 CRC32 0x816f8092 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1516610672;
SET @@session.pseudo_thread_id=3;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1;
SET @@session.sql_mode=2097152;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33;
SET @@session.lc_time_names=0;
SET @@session.collation_database=DEFAULT;
BEGIN
;
# at 291
#180122 16:44:32 server id 43306 end_log_pos 338 CRC32 0x9f700cb0 Table_map: `test`.`a` mapped to number 219
# at 338
#180122 16:44:32 server id 43306 end_log_pos 380 CRC32 0x192a0649 Write_rows: table id 219 flags: STMT_END_F
### INSERT INTO `test`.`a`
### SET
### @1=3
### @2='x'
# at 380
#180122 16:44:47 server id 43306 end_log_pos 411 CRC32 0x1ef809c7 Xid = 7
COMMIT;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' ;
DELIMITER ;
# End of log file
;
;
从生成的binlog可知,只生成了表a的DML变更记录。
(2.2)开启GTID,显式开启事务并回滚事务。
执行的DML操作如下:
root@localhost:mysql3306.sock 16:52: [test]>flush logs;
Query OK, 0 rows affected (0.01 sec)
root@localhost:mysql3306.sock 16:52: [test]>begin;
Query OK, 0 rows affected (0.00 sec)
root@localhost:mysql3306.sock 16:52: [test]>insert into a values (4,"x");
Query OK, 1 row affected (0.00 sec)
root@localhost:mysql3306.sock 16:52: [test]>insert into b values (4,"x");
ERROR 1785 (HY000): Statement violates GTID consistency: Updates to non-transactional tables can only be done in either autocommitted statements or single-statement transactions, and never in the same statement as updates to transactional tables.
root@localhost:mysql3306.sock 16:52: [test]>rollback;
Query OK, 0 rows affected (0.08 sec)
root@localhost:mysql3306.sock 16:52: [test]>select * from a;
+----+------+
| id | name |
+----+------+
| 1 | x |
| 3 | x |
+----+------+
2 rows in set (0.00 sec)
root@localhost:mysql3306.sock 16:54: [test]>select * from b;
+------+------+
| id | name |
+------+------+
| 1 | x |
| 2 | x |
+------+------+
2 rows in set (0.00 sec)
从报错信息可知,在开启GTID模式下,非事务表的DML操作只能在autocommitted statements和single-statement transactions情况下执行,在一个显式事务中混合事务表和非事务表的DML操作是不被允许的。表a和表b都没有数据变更。
生成的相应binlog日志如下:
[root@mysql3 binlog]# mysqlbinlog -vv mysql-bin.000002 --base64-output=decode-rows
;
;
DELIMITER ;
# at 4
#180122 16:52:16 server id 43306 end_log_pos 123 CRC32 0x946808ab Start: binlog v 4, server v 5.7.18-log created 180122 16:52:16
# Warning: this binlog is either in use or was not closed properly.
# at 123
#180122 16:52:16 server id 43306 end_log_pos 194 CRC32 0x7c37ab8f Previous-GTIDs
# 5252f852-685e-11e7-8eeb-000c299fe44c:1
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' ;
DELIMITER ;
# End of log file
;
;
从生成的binlog可知,也没有生成对应的变更记录。
综上所述,在mysql未开启GTID模式下,显式执行的事务中如果包含了非事务表的DML,这些表的数据并不会回滚(非事务性表无回滚的概念),同时也会为了主从数据一致的缘故,生成对应的binlog日志。而开启GTID模式下,非事务表只能在autocommit=1模式下单独执行或者只包含单个SQL的事务里执行。可见,开启GTID模式,通过禁止非事务表混入显式事务的方式去更好的保证了事务ACID特性,这种方式更为安全。
binlog是如何记录mysql对事务表和非事务表的DML操作就先给大家讲到这里,对于其它相关问题大家想要了解的可以持续关注我们的行业资讯。我们的板块内容每天都会捕捉一些行业新闻及专业知识分享给大家的。