mysql的procedure错误回滚问题
先科普一点知识:mysql在一个事物中发生错误时,是不会回滚整个事物的。
我们先证明这点
mysql> desc wzy;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| x | int(11) | NO | PRI | NULL | |
| y | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
2 rows in set (0.09 sec)
这是表结构
我们建一个procedure用于测试
CREATE DEFINER=`root`@`%` PROCEDURE `err_test1`(in v_x int,in v_y int,in v_z int)
SQL SECURITY INVOKER
BEGIN
START TRANSACTION;
INSERT INTO wzy.wzy VALUES(v_x,v_x+1);
INSERT INTO wzy.wzy VALUES(v_y,v_y+2);
INSERT INTO wzy.wzy VALUES(v_z,v_z+3);
COMMIT;
END
mysql> call wzy.err_test1(1,2,3);
Query OK, 0 rows affected (0.09 sec)
mysql> select * from wzy;
+---+------+
| x | y |
+---+------+
| 1 | 2 |
| 2 | 4 |
| 3 | 6 |
+---+------+
3 rows in set (0.00 sec)
mysql> truncate table wzy;
Query OK, 0 rows affected (0.12 sec)mysql> call wzy.err_test1(1,1,3);
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
mysql> select * from wzy;
+---+------+
| x | y |
+---+------+
| 1 | 2 |
+---+------+
1 row in set (0.00 sec)
先测试过程可用,再清空表
mysql> call wzy.err_test1(1,1,3);
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
mysql> select * from wzy;
+---+------+
| x | y |
+---+------+
| 1 | 2 |
+---+------+
1 row in set (0.00 sec)
这次第二行数据与第一行主键冲突,过程结束,第三行数据并没有进入数据库,但是第一行数据还是进入了数据库
现在我们看下
DECLARE EXIT HANDLER FOR SQLEXCEPTION
和
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
两种方式处理的procedure,在错误时处理的不同。
DECLARE EXIT HANDLER FOR SQLEXCEPTION的部分
CREATE DEFINER=`root`@`%` PROCEDURE `err_test2`(in v_x int,in v_y int,in v_z int)
SQL SECURITY INVOKER
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
START TRANSACTION;
INSERT INTO wzy.wzy VALUES(v_x,v_x+1);
INSERT INTO wzy.wzy VALUES(v_y,v_y+2);
INSERT INTO wzy.wzy VALUES(v_z,v_z+3);
COMMIT;
END
清空表,跑包
mysql> truncate table wzy;
Query OK, 0 rows affected (0.06 sec)
mysql> call err_test2(1,1,3);
Query OK, 0 rows affected (0.01 sec)
mysql> select * from wzy;
+---+------+
| x | y |
+---+------+
| 1 | 2 |
+---+------+
1 row in set (0.00 sec)
我们发现只有第一行数据入库,与不声明exit情况相同
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION的部分
CREATE DEFINER=`root`@`%` PROCEDURE `err_test3`(in v_x int,in v_y int,in v_z int)
SQL SECURITY INVOKER
BEGIN
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
START TRANSACTION;
INSERT INTO wzy.wzy VALUES(v_x,v_x+1);
INSERT INTO wzy.wzy VALUES(v_y,v_y+2);
INSERT INTO wzy.wzy VALUES(v_z,v_z+3);
COMMIT;
END
清空,并执行
mysql> truncate table wzy;
Query OK, 0 rows affected (0.07 sec)
mysql> call err_test3(1,1,3);
Query OK, 0 rows affected (0.02 sec)
mysql> select * from wzy;
+---+------+
| x | y |
+---+------+
| 1 | 2 |
| 3 | 5 |
+---+------+
2 rows in set (0.00 sec)
我们看到1、3都被执行了。可见continue会忽略报错继续执行。
那我们该如何回滚整个包的事物呢?我们可以通过定义一个变量来判断是否进行回滚。
这里再对比下EXIT与CONTINUE的区别
EXCEPTION 的情况下用变量做判断。
CREATE DEFINER=`root`@`%` PROCEDURE `err_test4`(in v_x int,in v_y int,in v_z int)
SQL SECURITY INVOKER
BEGIN
DECLARE EXCEPTION INT DEFAULT 0;
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET EXCEPTION = 1;
START TRANSACTION;
INSERT INTO wzy.wzy VALUES(v_x,v_x+1);
INSERT INTO wzy.wzy VALUES(v_y,v_y+2);
INSERT INTO wzy.wzy VALUES(v_z,v_z+3);
IF EXCEPTION = 1 THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
END
mysql> truncate table wzy;
Query OK, 0 rows affected (0.13 sec)
mysql> select * from wzy;
Empty set (0.00 sec)
mysql> call err_test4(1,1,3);
Query OK, 0 rows affected (0.00 sec)
mysql> select * from wzy;
+---+------+
| x | y |
+---+------+
| 1 | 2 |
+---+------+
1 row in set (0.00 sec)
数据还是入库了!可见变量没有发挥作用。
CONTINUE 的情况
CREATE DEFINER=`root`@`%` PROCEDURE `err_test5`(in v_x int,in v_y int,in v_z int)
SQL SECURITY INVOKER
BEGIN
DECLARE EXCEPTION INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET EXCEPTION = 1;
START TRANSACTION;
INSERT INTO wzy.wzy VALUES(v_x,v_x+1);
INSERT INTO wzy.wzy VALUES(v_y,v_y+2);
INSERT INTO wzy.wzy VALUES(v_z,v_z+3);
IF EXCEPTION = 1 THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
END
mysql> truncate table wzy;
Query OK, 0 rows affected (0.24 sec)
mysql> call err_test5(1,1,3);
Query OK, 0 rows affected (0.15 sec)
mysql> select * from wzy;
Empty set (0.00 sec)
整个procedure都被回滚了!可见CONTINUE会执行到最后,变量发挥了作用
经过对比我们可以知道
EXIT会在执行错误时,直接跳出过程,不去执行剩下的语句,不利与判断回滚,而且不声明时,mysql默认就是这么处理的。
CONTINUE会在执行错误时,继续执行过程,我们可以通过设置变量判断这个过程是否需要回滚
mysql的procedure错误回滚问题相关推荐
- mysql更新数据能回滚吗_mysql更新数据能回滚吗?如何实现呢?
不熟悉使用mysql数据库的朋友们,可能会对其有非常多的小问题,例如说,mysql更新数据可以回滚吗?我们应该如何去实现呢? 操作数据库时候难免会因为"大意"而误操作,需要快速恢复 ...
- mysql回滚与错误提示_对mysql事务提交、回滚的错误理解 – jae – 博客园
一.起因 begin或者START TRANSACTION开始一个事务 rollback事务回滚 commit 事务确认 人们对事务的解释如下:事务由作为一个单独单元的一个或多个 这句话本身没有什么问 ...
- MySQL中的事务回滚机制
在 MySQL 中,恢复机制是通过回滚日志(undo log)实现的,所有事务进行的修改都会先记录到这个回滚日志中,然后在对数据库中的对应行进行写入. 当事务已经被提交之后,就无法再次回滚了. 回滚日 ...
- php myisam,php+mysql怎么实现事务回滚,表是MyISAM类型的?
MyISAM不支持事务,但如果遇到数据库错误,怎么实现回滚?例如: 一段程序要先插入a表,然后再插入b表. 逻辑如下行不行: aResut=doInsertA if(aResut){ bResult= ...
- MySQL调用mongodb事务回滚_SpringBoot整合MongoDB,在多数据源下实现事务回滚。
项目中用到了MongoDB,准备用来存储业务数据,前提是要实现事务,保证数据一致性,MongoDB从4.0开始支持事务,提供了面向复制集的多文档事务特性.能满足在多个操作,文档,集合,数据库之间的事务 ...
- mysql更新数据能回滚吗_MySQL数据回滚-误更新和删除时快速恢复
这世界上有后悔药 – www.houhuiyao.cc 后悔药数据恢复 站长语 前面的内容也提到过update或delete误更新删除了数据后如何恢复.实际生产环境中常常因各种不同场景导致一些办法有效 ...
- mysql新增表字段回滚_MySql学习笔记四
MySql学习笔记四 5.3.数据类型 数值型 整型 小数 定点数 浮点数 字符型 较短的文本:char, varchar 较长的文本:text, blob(较长的二进制数据) 日期型 原则:所选择类 ...
- mysql用jdbc执行回滚吗_java – mysql jdbc不成功回滚
我有一些 Java代码使用JDBC连接到 MySQL数据库,然后代码执行一些读操作然后单个更新,所有使用相同的连接.如果有异常,则调用connection.rollback();如果没有异常,则调用c ...
- MySQL的rollback--事务回滚
MySQL version:5.7 首先:事务回滚只用于DML,不适用于DDL.对于DDL的回滚,以后有时间再说. 关于rollback和commit,MySQL的文档已经说的很详细了,选择其中一个简 ...
最新文章
- (莱昂氏unix源代码分析导读-46)权限、管道
- Apache构建web主机、日志分割及AWStats分析系统
- 深入理解Python中的元类(metaclass)
- 学成在线--21.课程信息修改
- elasticsearch date_MySQL数据实时增量同步到Elasticsearch
- mac电脑安装mysql
- Funcode实现打飞虫1
- 考研高等数学张宇30讲笔记——第七讲 零点问题与微分不等式
- TPU原理技术与xPU
- 计算机联锁静态数据表,计算机联锁功能.doc
- 屏幕录制软件哪个好?
- 安卓编程入门 06 开始接触后台代码
- 疯狂HTML5 CSS 3 JavaScript讲义 (李刚) 高清PDF扫描版
- xlsxwriter模块安装linux,XlsxWriter模块常用方法
- excel工作表合并
- (附源码)spring boot网上购物系统 毕业设计 311236
- 【2020-10-27】 scrapy爬虫之猎聘招聘信息爬取
- 单片机——LCD1602
- Markdown编辑器推荐
- HTML 标签简写及全称以及HTML总结
热门文章
- mysql安装 未将对象引用设置到对象的实例._未将对象引用设置到对象的实例--可能出现的问题总结...
- Android RecyclerView +SnapHelper 实现横向滚动自动滚动到中心控件并选中
- URAL 1294 Mars Satellites(圆内接三角形)
- CMD创建文件的方法及CMD打开常用工具的命令
- 阿里巴巴Java开发手册阅读笔记
- Tar 压缩时通配符的问题
- 电商项目实战之缓存与Redis分布式锁
- 利用Loadrunner+Fiddler抓包的形式录制APP的性能脚本
- jq设置保留两位小数_javascript实现保留两位小数的多种方法
- java毕业生设计安全生产监管系统计算机源码+系统+mysql+调试部署+lw