玩转Mysql系列 - 第20篇:异常捕获及处理详解

本文详细介绍了MySQL中的异常处理,包括内部异常和外部异常的分类,以及如何通过存储过程和乐观锁来捕获和处理异常。通过示例展示了在并发情况下如何利用乐观锁防止数据错误,确保事务一致性。
摘要由CSDN通过智能技术生成

Mysql系列的目标是:通过这个系列从入门到全面掌握一个高级开发所需要的全部技能。

欢迎大家加我微信itsoku一起交流java、算法、数据库相关技术。

这是Mysql系列第20篇。

环境:mysql5.7.25,cmd命令中进行演示。

代码中被[]包含的表示可选,|符号分开的表示可选其一。

需求背景

我们在写存储过程的时候,可能会出现下列一些情况:

  1. 插入的数据违反唯一约束,导致插入失败

  2. 插入或者更新数据超过字段最大长度,导致操作失败

  3. update影响行数和期望结果不一致

遇到上面各种异常情况的时,可能需要我们能够捕获,然后可能需要回滚当前事务。

本文主要围绕异常处理这块做详细的介绍。

此时我们需要使用游标,通过游标的方式来遍历select查询的结果集,然后对每行数据进行处理。

本篇内容

  • 异常分类详解

  • 内部异常详解

  • 外部异常详解

  • 掌握乐观锁解决并发修改数据出错的问题

  • update影响行数和期望结果不一致时的处理

准备数据

创建库:javacode2018

创建表:test1,test1表中的a字段为主键。


        
        
        
  1. /*建库javacode2018*/
  2. drop database  if exists javacode2018;
  3. create database javacode2018;
  4. /*切换到javacode2018库*/
  5. use javacode2018;
  6. DROP  TABLE  IF  EXISTS test1;
  7. CREATE  TABLE  test1(a int  PRIMARY  KEY);

异常分类

我们将异常分为mysql内部异常和外部异常

mysql内部异常

当我们执行一些sql的时候,可能违反了mysql的一些约束,导致mysql内部报错,如插入数据违反唯一约束,更新数据超时等,此时异常是由mysql内部抛出的,我们将这些由mysql抛出的异常统称为内部异常。

外部异常

当我们执行一个update的时候,可能我们期望影响1行,但是实际上影响的不是1行数据,这种情况:sql的执行结果和期望的结果不一致,这种情况也我们也把他作为外部异常处理,我们将sql执行结果和期望结果不一致的情况统称为外部异常。

Mysql内部异常

示例1

test1表中的a字段为主键,我们向test1表同时插入2条数据,并且放在一个事务中执行,最终要么都插入成功,要么都失败。

创建存储过程:

        
        
        
  1. /*删除存储过程*/
  2. DROP  PROCEDURE  IF  EXISTS proc1;
  3. /*声明结束符为$*/
  4. DELIMITER $
  5. /*创建存储过程*/
  6. CREATE  PROCEDURE  proc1(a1 int,a2 int)
  7.    BEGIN
  8.      START  TRANSACTION;
  9.      INSERT  INTO  test1(a)  VALUES (a1);
  10.      INSERT  INTO  test1(a)  VALUES (a2);
  11.      COMMIT;
  12.    END $
  13. /*结束符置为;*/
  14. DELIMITER ;

上面存储过程插入了两条数据,a的值都是1。

验证结果:

        
        
        
  1. mysql>  DELETE  FROM test1;
  2. Query  OK0 rows affected ( 0.00 sec)
  3. mysql>  CALL  proc1( 1, 1);
  4. ERROR  1062 ( 23000):  Duplicate entry  '1'  for key  'PRIMARY'
  5. mysql>  SELECT *  from test1;
  6. +---+
  7. | a |
  8. +---+
  9. 1 |
  10. +---+
  11. 1 row  in set ( 0.00 sec)

上面先删除了test1表中的数据,然后调用存储过程proc1,由于test1表中的a字段是主键,插入第二条数据时违反了a字段的主键约束,mysql内部抛出了异常,导致第二条数据插入失败,最终只有第一条数据插入成功了。

上面的结果和我们期望的不一致,我们希望要么都插入成功,要么失败。

那我们怎么做呢?我们需要捕获上面的主键约束异常,然后发现有异常的时候执行rollback回滚操作,改进上面的代码,看下面示例2。

示例2

我们对上面示例进行改进,捕获上面主键约束异常,然后进行回滚处理,如下:

创建存储过程:

        
        
        
  1. /*删除存储过程*/
  2. DROP  PROCEDURE  IF  EXISTS proc2;
  3. /*声明结束符为$*/
  4. DELIMITER $
  5. /*创建存储过程*/
  6. CREATE  PROCEDURE  proc2(a1 int,a2 int)
  7.    BEGIN
  8.      /*声明一个变量,标识是否有sql异常*/
  9.      DECLARE hasSqlError int  DEFAULT  FALSE;
  10.      /*在执行过程中出任何异常设置hasSqlError为TRUE*/
  11.      DECLARE  CONTINUE  HANDLER  FOR  SQLEXCEPTION  SET hasSqlError= TRUE;
  12.      /*开启事务*/
  13.      START  TRANSACTION;
  14.      INSERT  INTO  test1(a)  VALUES (a1);
  15.      INSERT  INTO  test1(a) 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值