mysql事务表和非事务表在binlog日志的不同处理

mysql的binlog日志是维系mysql主从同步的重要媒介。binlog日志对SQL记录策略,直接影响到主从之间的数据一致性。接下来我们来实验下,看看mysql对事务表和非事务表的DML操作,binlog是如何记录的。

实验环境: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操作如下:
[email protected]:mysql3306.sock  16:28:  [test]>begin;
Query OK, 0 rows affected (0.00 sec)
[email protected]:mysql3306.sock  16:28:  [test]>insert into a values (1,"x");
Query OK, 1 row affected (0.00 sec)
[email protected]:mysql3306.sock  16:29:  [test]>insert into b values (1,"x"); 
Query OK, 1 row affected (0.00 sec)
[email protected]:mysql3306.sock  16:29:  [test]>commit;
Query OK, 0 rows affected (0.00 sec)
生成的相应binlog日志如下:
[[email protected] binlog]# mysqlbinlog -vv mysql-bin.000001 --base64-output=decode-rows
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @[email protected]@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
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/*!*/;
/*!\C utf8 *//*!*/;
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 /* INT meta=0 nullable=1 is_null=0 */
###   @2='x' /* VARSTRING(30) meta=30 nullable=1 is_null=0 */
# 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 /* INT meta=0 nullable=0 is_null=0 */
###   @2='x' /* VARSTRING(30) meta=30 nullable=1 is_null=0 */
# at 679
#180122 16:29:05 server id 43306  end_log_pos 710 CRC32 0x5b9b8331      Xid = 58
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET [email protected]_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

从生成的binlog来看,不管是Myisam还是Innodb引擎,都生成相应的binlog日志。

(1.2)关闭GTID,显式开启事务并回滚事务

执行的DML操作如下:
[email protected]:mysql3306.sock  16:29:  [test]>flush logs;
Query OK, 0 rows affected (0.01 sec)
[email protected]:mysql3306.sock  16:35:  [test]>begin;
Query OK, 0 rows affected (0.01 sec)
[email protected]:mysql3306.sock  16:35:  [test]>insert into a values (2,"x"); 
Query OK, 1 row affected (0.00 sec)
[email protected]:mysql3306.sock  16:36:  [test]>insert into b values (2,"x"); 
Query OK, 1 row affected (0.00 sec)
[email protected]:mysql3306.sock  16:36:  [test]>rollback;
Query OK, 0 rows affected, 1 warning (0.01 sec)
当前表的数据如下:
[email protected]:mysql3306.sock  16:36:  [test]>select * from a;
+----+------+
| id | name |
+----+------+
|  1 | x    |
+----+------+
1 row in set (0.00 sec)

[email protected]:mysql3306.sock  16:37:  [test]>select * from b;
+------+------+
| id   | name |
+------+------+
|    1 | x    |
|    2 | x    |
+------+------+
2 rows in set (0.00 sec)
生成的相应binlog日志如下:
[[email protected] binlog]# mysqlbinlog -vv mysql-bin.000002 --base64-output=decode-rows
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @[email protected]@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
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/*!*/;
/*!\C utf8 *//*!*/;
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 /* INT meta=0 nullable=1 is_null=0 */
###   @2='x' /* VARSTRING(30) meta=30 nullable=1 is_null=0 */
# 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' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET [email protected]_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

从生成的binlog可知,表a回滚了数据,而表b由于是非事务表的缘故,没有回滚数据。同时表b的数据变更也生成对应的binlog日志。而表a由于事务回滚的缘故,没有变更数据,也没有生成binlog。

(2.1)开启GTID,显式开启事务并提交事务。

执行的DML操作如下:
[email protected]:mysql3306.sock  16:44:  [test]>begin;
Query OK, 0 rows affected (0.00 sec)
[email protected]:mysql3306.sock  16:44:  [test]>insert into a values (3,"x"); 
Query OK, 1 row affected (0.02 sec)
[email protected]: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.
[email protected]:mysql3306.sock  16:44:  [test]>commit;
Query OK, 0 rows affected (0.01 sec)

从报错信息可知,在开启GTID模式下,非事务表的DML操作只能在autocommitted statements和single-statement transactions情况下执行,在一个显式事务中混合事务表和非事务表的DML操作是不被允许的。

生成的相应binlog日志如下:
[[email protected] binlog]# mysqlbinlog -vv mysql-bin.000001 --base64-output=decode-rows
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @[email protected]@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
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/*!*/;
/*!\C utf8 *//*!*/;
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 /* INT meta=0 nullable=0 is_null=0 */
###   @2='x' /* VARSTRING(30) meta=30 nullable=1 is_null=0 */
# at 380
#180122 16:44:47 server id 43306  end_log_pos 411 CRC32 0x1ef809c7      Xid = 7
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET [email protected]_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

从生成的binlog可知,只生成了表a的DML变更记录。

(2.2)开启GTID,显式开启事务并回滚事务。

执行的DML操作如下:
[email protected]:mysql3306.sock  16:52:  [test]>flush logs;
Query OK, 0 rows affected (0.01 sec)
[email protected]:mysql3306.sock  16:52:  [test]>begin;
Query OK, 0 rows affected (0.00 sec)
[email protected]:mysql3306.sock  16:52:  [test]>insert into a values (4,"x");
Query OK, 1 row affected (0.00 sec)
[email protected]: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.
[email protected]:mysql3306.sock  16:52:  [test]>rollback;
Query OK, 0 rows affected (0.08 sec)
[email protected]:mysql3306.sock  16:52:  [test]>select * from a;
+----+------+
| id | name |
+----+------+
|  1 | x    |
|  3 | x    |
+----+------+
2 rows in set (0.00 sec)

[email protected]: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日志如下:
[[email protected] binlog]# mysqlbinlog -vv mysql-bin.000002 --base64-output=decode-rows
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @[email protected]@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
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' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET [email protected]_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

从生成的binlog可知,也没有生成对应的变更记录。

综上所述,在mysql未开启GTID模式下,显式执行的事务中如果包含了非事务表的DML,这些表的数据并不会回滚(非事务性表无回滚的概念),同时也会为了主从数据一致的缘故,生成对应的binlog日志。而开启GTID模式下,非事务表只能在autocommit=1模式下单独执行或者只包含单个SQL的事务里执行。可见,开启GTID模式,通过禁止非事务表混入显式事务的方式去更好的保证了事务ACID特性,这种方式更为安全。

原文地址:http://blog.51cto.com/linzhijian/2063741

时间: 2024-11-10 17:40:17

mysql事务表和非事务表在binlog日志的不同处理的相关文章

MySQL 事务表和非事务表

MySQL 事务表和非事务表 查看 max_binlog_stmt_cache_size 参数解释时(入门教程qkxue.net),有这么一句话 If nontransactional statements within a transaction require more than this many bytes of memory, the server generates an error. 那么,什么是 nontransactional statements ? 在 http://dev

通过binlog日志恢复表记录

使用binlog日志 1 使用binlog日志1.1 问题 利用binlog恢复库表,要求如下: 启用binlog日志 创建db1库tb1表,插入3条记录 删除tb1表中刚插入的3条记录 使用mysqlbinlog恢复删除的3条记录 1.2 步骤 实现此案例需要按照如下步骤进行. 步骤一:启用binlog日志 1)调整/etc/my.cnf配置,并重启服务 [[email protected] ~]# vim /etc/my.cnf [mysqld] .. .. log-bin-index=my

spring 中常用的两种事务配置方式以及事务的传播性、隔离级别

转载:http://blog.csdn.net/qh_java/article/details/51811533 一.注解式事务 1.注解式事务在平时的开发中使用的挺多,工作的两个公司中看到很多项目使用了这种方式,下面看看具体的配置demo. 2.事务配置实例 (1).spring+mybatis 事务配置 [html] view plain copy <!-- 定义事务管理器 --> <bean id="transactionManager" class="

使用binlog日志, XtraBackup备份工具 ,MySQL AB复制

使用binlog日志 1.1 问题 利用binlog恢复库表,要求如下: 启用binlog日志 创建db1库tb1表,插入3条记录 删除tb1表中刚插入的3条记录 使用mysqlbinlog恢复删除的3条记录 1.2 步骤 实现此案例需要按照如下步骤进行. 步骤一:启用binlog日志 1)调整/etc/my.cnf配置,并重启服务 [[email protected] ~]# vim /etc/my.cnf [mysqld] .. .. log-bin-index=mysql-bin     

Mysql之binlog日志说明及利用binlog日志恢复数据操作记录

众所周知,binlog日志对于mysql数据库来说是十分重要的.在数据丢失的紧急情况下,我们往往会想到用binlog日志功能进行数据恢复(定时全备份+binlog日志恢复增量数据部分),化险为夷! 废话不多说,下面是梳理的binlog日志操作解说: 一.初步了解binlogMySQL的二进制日志binlog可以说是MySQL最重要的日志,它记录了所有的DDL和DML语句(除了数据查询语句select),以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二进制日志是事务安全型的. DDL-

mysql binlog日志的三种模式

1.statement level模式 每一条会修改数据的sql都会记录到master的bin-log中.slave在复制的时候sql进程会解析成和原来master端执行过的相同的sql来再次执行.优点:statement level下的优点,首先就是解决了row level下的缺点,不需要记录每一行数据的变化,减少bin-log日志量,节约io,提高性能.因为他只需要记录在master上所执行的语句的细节,以及执行语句时候的上下文的信息.缺点:由于它是记录的执行语句,所以为了让这些语句在sla

mysql主从binlog日志自动清理及手动删除

问题反馈: mysql主从,在没有设置自动清理binlog日志的情况下,会产生庞大的同步日志文件,占用磁盘空间. 1 手动清理binlog日志,purge master logs 1.1 删除在"指定日期前"或"指定日志前"的所有二进制binlog日志文件   PURGE {MASTER | BINARY} LOGS TO 'log_name'     PURGE {MASTER | BINARY} LOGS BEFORE 'date' 实例: PURGE MAST

MySQL binlog日志三种模式选择及配置

在讲解binlog日志三种模式前,先了解一下解析binlog日志的命令工mysqlbinlog.mysqlbinlog工具的作用是解析mysql的二进制binlog日志内容,把二进制日志解析成可以在MySQL数据库里执行的SQL语句.binlog日志原始数据是以二进制形式存在的,需要使用mysqlbinlog工具转换成SQL语句形式.mysql的binlog日志作用是用来记录mysql内部增删改等对mysql数据库有更新内容的记录(对数据库进行改动的操作),对数据库查询的语句如show,sele

[数据库事务与锁]详解五: MySQL中的行级锁,表级锁,页级锁

注明: 本文转载自http://www.hollischuang.com/archives/914 在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足. 在数据库的锁机制中介绍过,在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎).表级锁(MYISAM引擎)和页级锁(BDB引擎 ). 行级锁 行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁.行级锁能大大减少数据库操作的冲突.其加锁粒度最小,但加锁的