赞
踩
失效的几种原因:
一、数据库或者数据表的存储引擎不是Innodb。
数据库与表的存储引擎必须是Innodb;因为这个存储引擎才支持事务;
二、使用 出错时跳过错误(DECLARE CONTINUE HANDLE FOR SQLEXCEPTION),却没有把自动提交关闭。如果使用出错跳出(DECLARE EXIT HANDLE FOR SQLEXCEPTION),则不需要关闭自动提交。
在开启事务时一定要把 autocommit 自动提交关闭 (set @@autocommit = 0);关闭当前会话自动提交功能,在Commit/Rollback后再打开(看你的需求,一般来说是要打开的,否则会影响其他业务的执行);
三、事务中间使用非DML语言导致Rollback无效。Rollback只能回滚DML语言。比如使用truncate清空表格将无法逆转,无法回滚。在事务中一定不能使用非DML 语言.
四、innodb_rollback_on_timeout = off 也可能导致 回滚失效 设置为 on
五、一般来说,如果存储过程出现了错误,就不要继续执行了。就像程序出错一样,出错了就不再往下执行。所以推荐EXIT来处理回滚。
- DECLARE EXIT HANDLER for SQLEXCEPTION
- begin
- set t_error = 1;
- ROLLBACK;
- end;
而非 DECLARE CONTINUE HANDLER FOR SQLEXCEPTION 去处理回滚,如果使用 CONTINUE 请参考第二条。
如果使用 DECLARE CONTINUE HANDLE FOR SQLEXCEPTION 处理 则可能遇到的跟我同一个问题,请看下面。
着重讲下为什么自动提交会导致Rollback失效呢?今天我可是吃了这个大亏,记录一下!
上图:
首先启动两个会话,我的事务等级是串行化
第一步第一个会话输入指令;
start transaction;
select * from test;
没有问题完美执行;
第二步第二个会话输入指令;
start transaction;
select * from test;
完美执行;
第三步第一个会话输入指令;
insert into test values('a',1);
出现等待,第二个会话也在使用test表,等待第二个会话的释放
第四步第二个回话输入指令;
insert into test values('b',1);
这时候直接报错->fuck,叫我重新开启事务,第一回话这时候运行通过;
第五步,第一个会话中输入指令;
insert into test values('a',2);
insert into test values('a',3);
rollback;
都完美运行,
第六步,第二个会话中输入指令;
insert into test values('b',2);
insert into test values('b',3);
rollback;
也完美运行;
接下来
select * from test;
我艹,
有两条记录,说明第二个会话中的rollback 未能得到运行;
分享原因,
在会话2报错后,前面的insert被回滚了;这时候事务被终止;
由于开启了自动提交
insert into test values('b',2);
insert into test values('b',3);
被自动提交了;
后面的rollback未起到作用;
在开启事务时自动提交会被禁用,当事务终止后自动提交又被开启!被坑的好惨...
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。