导读
有时候会发生事务超时的情况,此时MySQL会返回类似这样的错误:
那事务超时后会发生什么呢? 此时就需要注意到innodb_rollback_on_timeout了。
innodb_rollback_on_timeout变量
这是官方文档5.7的对innodb_rollback_on_timeout的解释:
In MySQL 5.7,InnoDBrolls back only the last statement on a transaction timeout by default. If --innodb_rollback_on_timeout is specified, a transaction timeout causes InnoDB to abort and roll back the entire transaction.
由官方文档知道 innodb_rollback_on_timeout 默认值为 OFF ,在 OFF 的时候事务超时后会回滚事务内最新执行的一条语句.如果值为 ON 会回滚整个事务。
验证
1、准备阶段
1)、在验证之前为了避免时间浪费,可以把超时时间特别调整为10秒。
session a: db01>set @@session.innodb_lock_wait_timeout=10;
Query OK, 0 rows affected (0.00 sec)
、创建测试用的表和插入必要的测试数据:
session a: db01> create table t1( idint not null primary key, age int );
Query OK, 0 rows affected (0.03 sec)
session a: db01> insert into t1 values(1,1),(2,2);
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
3)、开启两个session,分别命名为A和B。
注意:建表的时候,如果选择的字段(where里面用的)没有加索引,会造成加表锁,影响测试.
2、先来验证innodb_rollback_on_timeout=off的情况
innodb_rollback_on_timeout=off的情况下,显示开启事务,造成锁等待超时时,会回滚造成超时的那条语句,但是事务不会结束.
3、验证innodb_rollback_on_timeout=on的情况
注意:
innodb_rollback_on_timeout不支持动态修改,修改需要停服务。
innodb_rollback_on_timeout=on的情况下,5.6版本和5.7版本的行为会不一样.为了避免麻烦,一并在下表做对比。
innodb_rollback_on_timeout=on时,在5.6的版本下,由上文加粗加红的字体可以看到事务的ID的发祥变化,说明开启了一个新的事务.由此明白事务会整体回滚,然后新开一个事务接收下一次查询.但是在5.7版本下,回滚之后就不会再新开启一个事务了。
总结
如果使用MySQL 5.6:
innodb_rollback_on_timeout=off的情况下,会回滚最后造成锁等待的语句,事务没有自动结束.但是这样会造成数据的不一致.破坏了事务的原子性。
innodb_rollback_on_timeout=on的情况下,整个事务回滚后会自动创建一个事务。
如果使用MySQL 5.7:
innodb_rollback_on_timeout=off的情况下和5.6版本是一样的。
innodb_rollback_on_timeout=on的情况下,整个事务已经自动回滚,不会再自动创建事务。
所以不管是5.6的版本还是5.7的版本innodb_rollback_on_timeout最好都设置成ON,这样可以避免破坏事务原子性,保证数据一致性.唯一区别是在5.7版本下需要自己手动开启一个事务。