先科普一点知识: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错误回滚问题相关推荐

  1. mysql更新数据能回滚吗_mysql更新数据能回滚吗?如何实现呢?

    不熟悉使用mysql数据库的朋友们,可能会对其有非常多的小问题,例如说,mysql更新数据可以回滚吗?我们应该如何去实现呢? 操作数据库时候难免会因为"大意"而误操作,需要快速恢复 ...

  2. mysql回滚与错误提示_对mysql事务提交、回滚的错误理解 – jae – 博客园

    一.起因 begin或者START TRANSACTION开始一个事务 rollback事务回滚 commit 事务确认 人们对事务的解释如下:事务由作为一个单独单元的一个或多个 这句话本身没有什么问 ...

  3. MySQL中的事务回滚机制

    在 MySQL 中,恢复机制是通过回滚日志(undo log)实现的,所有事务进行的修改都会先记录到这个回滚日志中,然后在对数据库中的对应行进行写入. 当事务已经被提交之后,就无法再次回滚了. 回滚日 ...

  4. php myisam,php+mysql怎么实现事务回滚,表是MyISAM类型的?

    MyISAM不支持事务,但如果遇到数据库错误,怎么实现回滚?例如: 一段程序要先插入a表,然后再插入b表. 逻辑如下行不行: aResut=doInsertA if(aResut){ bResult= ...

  5. MySQL调用mongodb事务回滚_SpringBoot整合MongoDB,在多数据源下实现事务回滚。

    项目中用到了MongoDB,准备用来存储业务数据,前提是要实现事务,保证数据一致性,MongoDB从4.0开始支持事务,提供了面向复制集的多文档事务特性.能满足在多个操作,文档,集合,数据库之间的事务 ...

  6. mysql更新数据能回滚吗_MySQL数据回滚-误更新和删除时快速恢复

    这世界上有后悔药 – www.houhuiyao.cc 后悔药数据恢复 站长语 前面的内容也提到过update或delete误更新删除了数据后如何恢复.实际生产环境中常常因各种不同场景导致一些办法有效 ...

  7. mysql新增表字段回滚_MySql学习笔记四

    MySql学习笔记四 5.3.数据类型 数值型 整型 小数 定点数 浮点数 字符型 较短的文本:char, varchar 较长的文本:text, blob(较长的二进制数据) 日期型 原则:所选择类 ...

  8. mysql用jdbc执行回滚吗_java – mysql jdbc不成功回滚

    我有一些 Java代码使用JDBC连接到 MySQL数据库,然后代码执行一些读操作然后单个更新,所有使用相同的连接.如果有异常,则调用connection.rollback();如果没有异常,则调用c ...

  9. MySQL的rollback--事务回滚

    MySQL version:5.7 首先:事务回滚只用于DML,不适用于DDL.对于DDL的回滚,以后有时间再说. 关于rollback和commit,MySQL的文档已经说的很详细了,选择其中一个简 ...

最新文章

  1. (莱昂氏unix源代码分析导读-46)权限、管道
  2. Apache构建web主机、日志分割及AWStats分析系统
  3. 深入理解Python中的元类(metaclass)
  4. 学成在线--21.课程信息修改
  5. elasticsearch date_MySQL数据实时增量同步到Elasticsearch
  6. mac电脑安装mysql
  7. Funcode实现打飞虫1
  8. 考研高等数学张宇30讲笔记——第七讲 零点问题与微分不等式
  9. TPU原理技术与xPU
  10. 计算机联锁静态数据表,计算机联锁功能.doc
  11. 屏幕录制软件哪个好?
  12. 安卓编程入门 06 开始接触后台代码
  13. 疯狂HTML5 CSS 3 JavaScript讲义 (李刚) 高清PDF扫描版
  14. xlsxwriter模块安装linux,XlsxWriter模块常用方法
  15. excel工作表合并
  16. (附源码)spring boot网上购物系统 毕业设计 311236
  17. 【2020-10-27】 scrapy爬虫之猎聘招聘信息爬取
  18. 单片机——LCD1602
  19. Markdown编辑器推荐
  20. HTML 标签简写及全称以及HTML总结

热门文章

  1. mysql安装 未将对象引用设置到对象的实例._未将对象引用设置到对象的实例--可能出现的问题总结...
  2. Android RecyclerView +SnapHelper 实现横向滚动自动滚动到中心控件并选中
  3. URAL 1294 Mars Satellites(圆内接三角形)
  4. CMD创建文件的方法及CMD打开常用工具的命令
  5. 阿里巴巴Java开发手册阅读笔记
  6. Tar 压缩时通配符的问题
  7. 电商项目实战之缓存与Redis分布式锁
  8. 利用Loadrunner+Fiddler抓包的形式录制APP的性能脚本
  9. jq设置保留两位小数_javascript实现保留两位小数的多种方法
  10. java毕业生设计安全生产监管系统计算机源码+系统+mysql+调试部署+lw