http://www.ywnds.com/?p=9560

一、innodb_rollback_on_timeout变量

有时侯会发生事务超时的情况,MySQL会返回类似这样的错误:

 
1
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction.

那事务超时后会发生什么呢?此时就需要注意到innodb_rollback_on_timeout了。

这是官方文档对innodb_rollback_on_timeout的解释:

在MySQL 5.6&5.7中默认值为OFF,当InnoDB默认情况下仅回滚事务超时的最后一条语句。如果innodb_rollback_on_timeout值为ON,则事务超时后将导致InnoDB中止并回滚整个事务。

二、验证innodb_rollback_on_timeout=off的情况

Session A

开启一个事务,使用读锁锁住一行数据。

 
1
2
3
4
5
6
7
session a: db01> start transaction;
session a: db01> select * from t1 where id = 1 lock in share mode ;
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
+----+------+

Session B

显示开启事务,插入数据后查询到事务ID是4891。

 
1
2
3
4
5
6
7
8
9
10
11
12
13
session b:db01> start transaction;
session b:db01> insert into t1 value(3,3);
session b:db01> select trx_id,trx_state,trx_mysql_thread_id,trx_query from information_schema.innodb_trx\G
*************************** 1. row ***************************
                    trx_id: 4891
                 trx_state: RUNNING
       trx_mysql_thread_id: 4
                 trx_query: select * from information_schema.innodb_trx
*************************** 2. row ***************************
                    trx_id: 4888
                 trx_state: RUNNING
       trx_mysql_thread_id: 5
                 trx_query: NULL

再在此事务中执行会造成锁等待的语句,超时后查询发现,数据(3,3)顺利插入,但是理应更新的数据(1,11)没有了,说明发生了文档所说的回滚最新的一条语句。 事务并不会自动结束,不然就会破坏事务的原子性。

 
1
2
3
4
5
6
7
8
9
10
11
session b:db01> update t1 set age = 11 where id = 1 ;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
session b:db01> select * from t1;
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+
3 rows in set (0.00 sec)

查询事务,发现4891事务还存在。

 
1
2
3
4
5
6
7
8
9
10
11
session b:db01> select trx_id,trx_state,trx_mysql_thread_id,trx_query from information_schema.innodb_trx\G
*************************** 1. row ***************************
                    trx_id: 4891
                 trx_state: RUNNING
       trx_mysql_thread_id: 4
                 trx_query: select * from information_schema.innodb_trx
*************************** 2. row ***************************
                    trx_id: 4888
                 trx_state: RUNNING
       trx_mysql_thread_id: 5
                 trx_query: NULL

如果此时Session B执行回滚事务,新插入的数据(3,3)被回滚了。那么Session A也就自然看不到曾经被更改的数据了(不针对读未提交隔离级别)。

如果Session B执行提交,在Session A可以看到数据(3,3) 。

 
1
session b:db01> commit ;

Session A

 
1
2
3
4
5
6
7
8
session a:db01>select * from t1 ;
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+

innodb_rollback_on_timeout=off的情况下,显示开启事务,造成锁等待超时时,会回滚造成超时的那条语句,但是事务不会结束。

三、验证innodb_rollback_on_timeout=on的情况

注意:

1. innodb_rollback_on_timeout不支持动态修改,修改需要停服务。

2. innodb_rollback_on_timeout=on的情况下,5.6版本和5.7版本的行为会不一样,为了避免麻烦,一并在下表做对比。

Session A(5.6&5.7)

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
session a: db01> select * from t1;
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
|  2 |    2 |
+----+------+
session a: db01> start transaction;
session a: db01> select * from t1 where id = 1 lock in share mode ;
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
+----+------+

Session B(5.6)

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
session b: db01> start transaction ;
session b: db01> insert into t1 value(3,3);
session b: db01> select * from t1;
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+
session b: db01> select trx_id,trx_state,trx_mysql_thread_id,trx_query from information_schema.innodb_trx\G
*************************** 1. row ***************************
             trx_id: 5388
          trx_state: RUNNING
trx_mysql_thread_id: 2
          trx_query: select trx_id,trx_state,trx_mysql_thread_id,trx_query from information_schema.innodb_trx
*************************** 2. row ***************************
             trx_id: 5387
          trx_state: RUNNING
trx_mysql_thread_id: 1
          trx_query: NULL

Session C(5.7)

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
session c: db01> start transaction ;
session c: db01> insert into t1 value(3,3);
session c: db01> select * from t1;
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+
session c: db01> select trx_id,trx_state,trx_mysql_thread_id,trx_query from information_schema.innodb_trx\G
*************************** 1. row ***************************
             trx_id: 3201284
          trx_state: RUNNING
trx_mysql_thread_id: 2
          trx_query: select trx_id,trx_state,trx_mysql_thread_id,trx_query from information_schema.innodb_trx
*************************** 2. row ***************************
             trx_id: 422128392099664
          trx_state: RUNNING
trx_mysql_thread_id: 3
          trx_query: NULL

Session B(5.6)和Session C(5.7)分别开启事务,插入数据(3,3)。查询到新增的事务分别是5388和3201284。

然后都执行会造成锁等待的语句:

Session B(5.6)

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
session b: db01> update t1 set age = 11 where id =1 ;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
session b: db01> select * from t1;
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
|  2 |    2 |
+----+------+
session b: db01> select trx_id,trx_state,trx_mysql_thread_id,trx_query from information_schema.innodb_trx\G
*************************** 1. row ***************************
             trx_id: 5401
          trx_state: RUNNING
trx_mysql_thread_id: 2
          trx_query: select trx_id,trx_state,trx_mysql_thread_id,trx_query from information_schema.innodb_trx
*************************** 2. row ***************************
             trx_id: 5387
          trx_state: RUNNING
trx_mysql_thread_id: 1
          trx_query: NULL

Session C(5.7)

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
session c: db01> update t1 set age = 11 where id = 1 ;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
session c: db01> select * from t1;
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
|  2 |    2 |
+----+------+
session c: db01> select trx_id,trx_state,trx_mysql_thread_id,trx_query from information_schema.innodb_trx\G
*************************** 1. row ***************************
             trx_id: 422128392099664
          trx_state: RUNNING
trx_mysql_thread_id: 3
          trx_query: NULL

超时后再查询发现:

1. 新插入的数据都回滚了。

2. Session B(5.6)原先的事务5388已经不见了,新增加了一个事务5401。说明5.6版本情况下,innodb_rollback_on_timeout=on,锁超时后,接收下一句语句时会立即开启一个新事务。

3. Session C(5.7)原先的事务3201284已经不见了。

再验证不显示开始事务的情况,发现此时Session B(5.6)没有自动开启事务。

 
1
2
3
4
5
6
7
8
9
session b: db01> rollback ;
session b: db01> update t1 set age = 11 where id =1 ;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
session b: db01> select trx_id,trx_state,trx_mysql_thread_id,trx_query from information_schema.innodb_trx\G
*************************** 1. row ***************************
             trx_id: 5387
          trx_state: RUNNING
trx_mysql_thread_id: 1
          trx_query: NULL
 
1
2
3
4
5
6
7
8
session c: db01> update t1 set age = 11 where id = 1 ;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
session c: db01> select trx_id,trx_state,trx_mysql_thread_id,trx_query from information_schema.innodb_trx\G
*************************** 1. row ***************************
             trx_id: 422128392099664
          trx_state: RUNNING
trx_mysql_thread_id: 3
          trx_query: NULL

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版本下需要自己手动开启一个事务。


如果您觉得本站对你有帮助,那么可

MySQL数据库innodb_rollback_on_timeout默认值的危害?的更多相关文章

  1. mysql设置datetime默认值为now

    mysql设置datetime默认值为now MYSQL-TIMESTAMP数据类型的默认值与自动更新问题 http://blog.csdn.net/scogeek/article/details/5 ...

  2. 查看MySQL数据库的默认编码

    查看MySQL数据库的默认编码 1.使用status命令能够显示数据库的相关系信息,示例如下: mysql> status;————–mysql Ver 14.12 Distrib 5.0.77 ...

  3. Mysql 修改字段默认值

    环境:MySQL 5.7.13 问题描述:建表的时候,users_info表的role_id字段没有默认值,后期发现注册的时候,需要提供给用户一个默认角色,也就是给role_id字段一个默认值. 当前 ...

  4. mysql日期类型默认值'0000-00-00'容错处理

    mysql日期默认值'0000-00-00'惹的祸 .net连mysql数据库时,如果表里有字段是日期型且值是‘0000-00-00’时,会报错.在C#里面日期不可能是那样的.或许是最小日期定义的差别 ...

  5. hibernate设置mysql的timestamp默认值技巧

    首先,要想使用数据库中配置的默认值就必须不让hibernate覆盖了默认值,需要配置property insert="false" update="false" ...

  6. 修改MySql数据库的默认时

    MySql数据库创建后,默认的时区比东八区少了八个小时.如果Sql语句中使用到MySql的时间的话就会比正常时间少了八个小时.所以需要修改MySql的系统时区,使其显示的时间和我们现在的时间一致. 1 ...

  7. jdbc,mysql 数据库BLOB返回值 [B 的问题

    当jdbc返回值类型对应的java类型是[B,那就表示返回值的类型比较模糊难以区分: BLOB类型是mysql数据库常用来存储,但是通过getBlob()方法获取值得时候会报错: 错误信息: java ...

  8. mysql数据库TINYINT取值范围详解

    分享下mysql中TINYINT的取值范围,很基础的一些内容. 在MySQL的数据类型中,Tinyint的取值范围是:带符号的范围是-128到127.无符号的范围是0到255(见官方<MySQL ...

  9. ADO.NET实体数据模型中关于数据库字段默认值的处理

    无论是Visual Studio 2010或者2013内置的ADO.NET实体数据模型都有一个小问题:数据库中有些字段已设置了默认值,但ADO.NET实体数据模型工具并不会自动进行设置. 这时需要手工 ...

随机推荐

  1. yaml文件 *.yml 写法简介

    YAML(Yet Another Markup Language)(发音 /ˈjæməl/ ) 一种基于Unicode容易阅读,容易和脚本语言交互的,用来表达资料序列的编程语言. 适应场景 脚本语言: ...

  2. 从零开始写一个npm包及上传

    最近刚好自己需要写公有npm包及上传,虽然百度上资料都能找到,但是都是比较零零碎碎的,个人就来整理下,如何从零开始写一个npm包及上传. 该篇文件只记录一个大概的流程,一些细节没有记录. tips:  ...

  3. 问题2:input、textarea、submit 宽度设置为100%,但显示宽度不一致

    <style type="text/css"> body{ padding: 10px; } input,textarea{ width: 100%; } </s ...

  4. iOS耳机监听

    1 .插入耳机的时候并没有切换到耳机播放 仍然是扬声器播放 2 .当一开始手机上已经插入耳机时 ,这时候开启音频播放时 仍然是扬声器播放 因此今天主要谈的就是从这两个问题: 先来解决第一个问题:其实解 ...

  5. 定时器修改button标题闪烁

    在做一个项目时,用到UIButton来设置接收短信验证码的倒计时,但是用NSTimer来设置标题会出现连续闪烁的问题. 经过测试发现了一下内容,如果只是单独的设置button的titleLabel的内 ...

  6. Js学习(2)数据类型

    Js共有六种数据类型(ES6又增加了第七种Symbol类型的值): 原始类型:数值,字符串,布尔值 合成类型:对象(object):各种值组成的集合 其他undefined,null 对象又可以分成三 ...

  7. 41-ssm中对象查找正确但是没有将数据库中某个属性值赋给对象的一个成员变量

    原因: 变量名虽然与 数据库字段一致,但是 包含下划线,如: a_b,数据库确实也是a_b: 但是ssm开启驼峰命名了,就要将变量名改为   aB , 驼峰命名就可以了.

  8. WEB框架之Django实现分页功能

    一 Paginator分页器 1 首先在数据库中生成大量数据 def index(request) book_list = [] for i in rang(1000) book = Book(tit ...

  9. 在textarea中鼠标指定的位置插入字符或表情

    有些时候我们已经在textarea中输入了一些字符,然后想在鼠标指定的位置插入表情或者字符,这就需要用到jquery的一个小插件了. 代码如下: (function ($) { $.fn.extend ...

  10. JFinal Model判断数据库某条记录的属性字段是否包含空值

    如果做报表,一条记录中有空值,使用FreeMarker渲染word会报错,并把错误日志输出到Word中.所以需要之前判断下当前记录中属性值是否有空值. package com.huijiasoft.u ...