MySQL InnoDB加锁超时回滚机制(转)
add by zhj: 看来我对MySQL的理解还有待深入,水还是挺深的啊,MySQL给记录加锁时,可以通过innodb_lock_wait_timeout参数设置超时时间,
如果加锁等待超过这个时间,就会回滚,但回滚的话有两种方式:第一种:回滚当前加锁的这条语句;第二种:回滚整个事务。这两种方式是通过参数
innodb_rollback_on_timeout来控制的。如果是OFF,表示加锁超时回滚时,只回滚加锁超时的那条SQL语句;如果是ON,表示回滚整个事务。默认
是OFF。在《MySQL Admin Cookbook》一书中,作者强烈建议该参数设置为ON,但其实OFF也没关系,你可以在应用程序中捕获那个加锁超时,然
后应用程序去执行ROLLBACK,这样就可以保证原子性,只要你没执行COMMIT,就不会破坏原子性。Django应该就是这么做的。我个人拙见是:感觉
设置为ON,依靠数据库本身自动完成回滚更好一些。
原文:http://www.cnblogs.com/hustcat/archive/2012/11/18/2775487.html
1、innodb_rollback_on_timeout变量
下面是MySQL官方手册关开innodb_rollback_on_timeout变量的说明:
In MySQL 5.0.13 and up, InnoDB rolls 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 (the same behavior as before MySQL 5.0.13). This variable was added in MySQL 5.0.32. |
该变量默认值为OFF,如果事务因为加锁超时,会回滚上一条语句执行的操作。如果设置ON,则整个事务都会回滚。
下面通过一个示例来验证上面这段话。
2、示例
(1) innodb_rollback_on_timeout为OFF
Session 1 |
Session 2 |
mysql> create table tt(c1 int primary key, c2 int)engine=innodb; Query OK, 0 rows affected (0.01 sec) mysql> insert into tt values(1, 1); Query OK, 1 row affected (0.00 sec) mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from tt where c1=1 lock in share mode; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | +----+------+ 1 row in set (0.00 sec) |
|
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> insert into tt values(10,10); Query OK, 1 row affected (0.00 sec) mysql> delete from tt where c1=1; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> select * from tt; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | | 10 | 10 | +----+------+ 2 rows in set (0.00 sec) mysql> rollback; Query OK, 0 rows affected (0.01 sec) mysql> select * from tt; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | +----+------+ 1 row in set (0.00 sec) |
|
mysql> select * from tt; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | +----+------+ 1 row in set (0.00 sec) |
|
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> insert into tt values(10,10); Query OK, 1 row affected (0.00 sec) mysql> delete from tt where c1=1; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> commit; Query OK, 0 rows affected (0.02 sec) mysql> select * from tt; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | | 10 | 10 | +----+------+ 2 rows in set (0.00 sec) |
session2因为加锁超时,事务回退到上一条语句。
(2) innodb_rollback_on_timeout为ON
Session 1 |
Session 2 |
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from tt where c1=1 lock in share mode; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | +----+------+ 1 row in set (0.00 sec) |
|
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> insert into tt values(11,11); Query OK, 1 row affected (0.00 sec) mysql> delete from tt where c1=1; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> select * from tt; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | | 10 | 10 | +----+------+ 2 rows in set (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> select * from tt; +----+------+ | c1 | c2 | +----+------+ | 1 | 1 | | 10 | 10 | +----+------+ 2 rows in set (0.00 sec) |
session2加锁超时,整个事务回滚。
3、总结
innodb_rollback_on_timeout为OFF,事务会回滚到上一个保存点,InnoDB在执行每条SQL语句之前,都会创建一个保存点,参见代码:
int row_insert_for_mysql( /* out: error code or DB_SUCCESS */ byte* mysql_rec, /* in: row in the MySQL format */ row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL handle */ { 。。。 savept = trx_savept_take(trx); 。。。 |
如果事务因为加锁超时,相当于回滚到上一条语句。但是报错后,事务还没有完成,用户可以选择是继续提交,或者回滚之前的操作,由用户选择是否进一步提交或者回滚事务。
innodb_rollback_on_timeout为ON,整个事务都会回滚。这可以从row_mysql_handle_errors函数中得到验证。
ibool
row_mysql_handle_errors(
/*====================*/
/* out: TRUE if it was a lock wait and
we should continue running the query thread */
ulint* new_err,/* out: possible new error encountered in
lock wait, or if no new error, the value
of trx->error_state at the entry of this
function */
trx_t* trx, /* in: transaction */
que_thr_t* thr, /* in: query thread */
trx_savept_t* savept) /* in: savepoint or NULL */
{
...
else if (err == DB_DEADLOCK //发生死锁
|| err == DB_LOCK_TABLE_FULL
|| (err == DB_LOCK_WAIT_TIMEOUT
&& row_rollback_on_timeout)) {
/* Roll back the whole transaction; this resolution was added
to version 3.23.43 */ trx_general_rollback_for_mysql(trx, FALSE, NULL); //事务全部回滚
} else if (err == DB_OUT_OF_FILE_SPACE
|| err == DB_LOCK_WAIT_TIMEOUT) { ut_ad(!(err == DB_LOCK_WAIT_TIMEOUT
&& row_rollback_on_timeout)); if (savept) { //回滚到上一个保存点
/* Roll back the latest, possibly incomplete
insertion or update */ trx_general_rollback_for_mysql(trx, TRUE, savept);
}
/* MySQL will roll back the latest SQL statement */
...
问题:innodb_rollback_on_timeout为OFF,事务的原子性被破坏了吗?
答:NO,从示例中可以看到,事务只是回退上一条语句的状态,而整个事务实际上没有完成(提交或者回滚),而作为应用程序在检测这个错误时,应该选择是提交或者回滚事务。如果严格要求事务的原子性,当然是执行ROLLBACK,回滚事务。
MySQL InnoDB加锁超时回滚机制(转)的更多相关文章
- mysql事务提交和回滚机制
应用场景: 银行取钱,从ATM机取钱,分为以下几个步骤 1 登陆ATM机,输入密码: 2 连接数据库,验证密码: 3 验证成功,获得用户信息,比如存款余额等: 4 用 ...
- Hadoop HDFS概念学习系列之HDFS升级和回滚机制(十二)
不多说,直接上干货! HDFS升级和回滚机制 作为一个大型的分布式系统,Hadoop内部实现了一套升级机制,当在一个集群上升级Hadoop时,像其他的软件升级一样,可能会有新的bug或一些会影响现有应 ...
- spring boot开启事务管理,使用事务的回滚机制,使两条插入语句一致
spring boot 事务管理,使用事务的回滚机制 1:配置事务管理 在springboot 启动类中添加 @EnableTransactionManagement //开启事务管理 @Enable ...
- oracle回滚机制深入研究
这篇文章主要描写叙述oracle的回滚机制,篇幅可能较长,由于对于oracle的回滚机制来说,要讨论和描写叙述的实在太多,仅仅能刷选自己觉得最有意义的一部分进行深入研究和分享 一.我们来看一个DML语 ...
- 关于MySQL回滚机制
在事务中,每个正确的原子操作都会被顺序执行,直到遇到错误的原子操作,此时事务会将之前的操作进行回滚.回滚的意思是如果之前是插入操作,那么会执行删 除插入的记录,如果之前是update操作,也会执行up ...
- mysql事务回滚机制概述
应用场景: 银行取钱,从ATM机取钱,分为以下几个步骤 1 登陆ATM机,输入密码: 2 连接数据库,验证密码: 3 验证成功,获得用户信息,比如存款余额等: 4 用 ...
- Spring中的事务回滚机制
初学者笔记 问题:在Java项目汇中,添加@Transactional注解,报错之后,事务回滚未生效,数据仍插入数据库中.经查看报错位置位于新增成功之后.空指针异常. 一.特性 先了解一下@Trans ...
- 【MySQL】使用mysqlbinlog回滚
参考:http://wubx.net/?s=mysqlbinlog mysql官方的mysqlbinlog没有回滚的功能,淘宝大牛对官方代码进行了修改使之能够将binlog中的DML操作变成互逆的语句 ...
- 对mysql事务提交、回滚的错误理解
一.起因 begin或者START TRANSACTION开始一个事务 rollback事务回滚 commit 事务确认 人们对事务的解释如下:事务由作为一个单独单元的一个或多个SQL语句组成,如果其 ...
随机推荐
- 【转】WPF自定义控件与样式(5)-Calendar/DatePicker日期控件自定义样式及扩展
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要内容: 日历控件Calendar自定义样式: 日期控件DatePicker自定 ...
- perl _DATA_ 文件句柄
常用的perl 读写文件的操作,我们都很熟悉了,需要先声明1个文件句柄.但是看下面这段代码: my %organisms = (); while(<DATA>){ chomp; if(/^ ...
- 关于tomcat7服务下面js无法获取JSESSIONID的cookie信息
http://tomcat.apache.org/tomcat-5.5-doc/config/context.html Does anyone know what changed in the con ...
- Keepalived 配置高可用集群
一.Keepalived 简介 (1) Keepalived 能实现高可用也能实现负载均衡,Keepalived 是通过 VRRP 协议 ( Virtual Router Redundancy Pro ...
- Android打印当前所有线程及对应栈信息
Map<Thread, StackTraceElement[]> threadMap = Thread.getAllStackTraces(); Log.e("albertThr ...
- Android Selinux
https://blog.csdn.net/rikeyone/article/details/84337115 如何快速定位SElinux问题并修复? https://blog.csdn.net/ ...
- iOS - 标准时间与时间戳相互转换
做倒计时后台传的不是时间戳,是时间然后需要与系统时间对比得出时间戳进行倒计时显示 #pragma mark -- 倒计时 // 倒计时时间 NSString* timeStr = task.recei ...
- PHP数组总结,,PHP面向对象思维思路。
<?php //定义数组 $attr = array(); $attr[] = ; //索引数组 $attr = array(,,,); //关联数组 $attr = array("c ...
- datagrid--新增
先在datagrid中添加toolbar配置项,增删改差的按钮,有3个属性,按钮名称,图标,回调函数,点击按钮会弹出一个对话框dialog,dialog是关闭的,closed=true, toolba ...
- VC++、Win32 SDK、MFC的区别
这是一个初进行开发人员都可能遇到过的概念不清的问题,自己当年也同样有过误解,做技术我感觉一定要专,但是,不代表毫不关心相关的知识,至少概念层次上要知道,所以,这里还是再把这些内容纪录下来,好记性不如烂 ...