• 数据库事务


    1 概述

    数据库的事务(Transaction)是一种机制、一个操作序列,包含了一组数据库操作命令

    事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么同时成功,要么同时失败

    事务是一个不可分割的工作逻辑单元。

    我们通过下图来理解

    在这里插入图片描述

    我们现在希望把所有的书籍都降价8元,但是我们不知道我们处理完了之后,我们的目的达成了没有,是否只有一部分书籍降价成功了,一部分没有,如果我们要求的是,没有全部都降价正确的话,那就集体不讲价,这个像不像我们一般安装软件,如果中途有一个步骤停止了,那么就直接rollback,下次安装的时候从头开始,之前的一切操作都无效。

    从上图可以看到在批量处理前开启事务,如果出现了异常回滚事务,三步正常执行就提交事务,这样就可以完美解决问题。

    4.2 语法

    • 开启事务

      START TRANSACTION;
      或者  
      BEGIN;
      
      • 1
      • 2
      • 3
    • 提交事务

      commit;
      
      • 1
    • 回滚事务

      rollback;
      
      • 1

    4.3 代码验证

    • 环境准备

      DROP TABLE IF EXISTS account;
      
      -- 创建账户表
      CREATE TABLE book(
      	recID int PRIMARY KEY auto_increment,
      	title varchar(10),
      	type varchar(20),
      	price double(10,2)
      );
      
      -- 添加数据
      INSERT INTO bookt(titile,type,price) values
      ('Java Programming','Computer',36.0),
      ('Java EE Technology','Computer',49.0),
      ('Information System','Computer',49.0)
      ;
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    • 不加事务演示问题

      -- 降价操作
      
      UPDATE book set price = price - 8 where recID = 1;
      UPDATE book set price = price - 8 where recID = 2;
      UPDATE book set price = price - 8 where recID = 3; 
      
      • 1
      • 2
      • 3
      • 4
      • 5

      如果有一句sql语句出错了,我们也不知道,然后错了就错了,就像我们安装软件一样,如果中途我们因为啥啥啥原因,安装失误了,然后我们重新安装,很多事情都需要重新做一次,但是之前的操作又没有撤回,这个时候很多操作会重复做很多很多次,然后就g了。

    • 添加事务sql如下:

      -- 开启事务
      BEGIN;
      UPDATE book set price = price - 8 where recID = 1;
      UPDATE book set price = price - 8 where recID = 2;
      UPDATE book set price = price - 8 where recID = 3; 
      
      -- 提交事务
      COMMIT;
      
      -- 回滚事务
      ROLLBACK;
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

      上面sql中的执行成功进选择执行提交事务,而出现问题则执行回滚事务的语句。以后我们肯定不可能这样操作,而是在java中进行操作,在java中可以抓取异常,没出现异常提交事务,出现异常回滚事务。

    4 事务的四大特征

    • 原子性(Atomicity): 事务是不可分割的最小操作单位,要么同时成功,要么同时失败

    • 一致性(Consistency) :事务完成时,必须使所有的数据都保持一致状态

    • 隔离性(Isolation) :多个事务之间,操作的可见性

    • 持久性(Durability) :事务一旦提交或回滚,它对数据库中的数据的改变就是永久的

    说明:

    mysql中事务是自动提交的。

    也就是说我们不添加事务执行sql语句,语句执行完毕会自动的提交事务。

    可以通过下面语句查询默认提交方式:

    SELECT @@autocommit;
    
    • 1

    查询到的结果是1 则表示自动提交,结果是0表示手动提交。当然也可以通过下面语句修改提交方式

    set @@autocommit = 0;
    
    • 1

    演示代码

    package com.study.jdbc;
    
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.Statement;
    
    
    /**
     * JDBC快速入门
     */
    public class JDBCDemo {
    
        public static void main(String[] args) throws Exception {
            //1. 注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2. 获取连接
            // String url = "jdbc:mysql://127.0.0.1:3306/books"; // 如果是mysql5这样写
            String url = "jdbc:mysql://localhost:3306/books?serverTimezone=GMT%2B8&useOldAliasMetadataBehavior=true"; // 如果是mysql8这样写
            String username = "root";
            String password = "1234";
    
            Connection conn = DriverManager.getConnection(url, username, password);
            //3. 定义sql
            String sql1 = "update book set price = price - 8 where reclD = 1";
            String sql2 = "update book set price = price - 8 where reclD = 2";
            String sql3 = "update book set price = price - 8 where reclD = 3";
            //4. 获取执行sql的对象 Statement
            Statement stmt = conn.createStatement();
    
            try {
                // ============开启事务==========
                conn.setAutoCommit(false); // 加上这几句之后 如果发生异常就会回滚 然后数据不会发生改变
                // 如果没有发生异常 但是发现数据库里面的数据没有改变
                // 可以把这里改成true 不改的话内存里面的数据改了 但是显示的没有改
                //5. 执行sql
                int count1 = stmt.executeUpdate(sql1);//受影响的行数
                //6. 处理结果
                System.out.println(count1);
                int i = 3/0;
                //5. 执行sql
                int count2 = stmt.executeUpdate(sql2);//受影响的行数
                //6. 处理结果
                System.out.println(count2);
                //5. 执行sql
                int count3 = stmt.executeUpdate(sql3);//受影响的行数
                //6. 处理结果
                System.out.println(count3);
    
                // ============提交事务==========
                //程序运行到此处,说明没有出现任何问题,则需求提交事务
                conn.commit();
            } catch (Exception e) {
                // ============回滚事务==========
                //程序在出现异常时会执行到这个地方,此时就需要回滚事务
                conn.rollback();
                e.printStackTrace();
            }
    
            //7. 释放资源
            stmt.close();
            conn.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    运行结果:
    在这里插入图片描述
    在上述代码运行过程中,发生了异常,然后使用事物处理的话,那么在此之前的一切修改都会撤销。
    内容没有变。
    在这里插入图片描述

  • 相关阅读:
    处理多维特征的输入
    面试计算机网络八股文十问十答第十期
    【Linux·克莱因计划】实用指令操作汇总合集(下)
    长沙:借网红的风,铺长红的路
    经典查找算法
    用HTTP proxy module配置一个简单反向代理服务器
    【Rust日报】2022-12-05 探索 docker 的 WASM 技术预览
    Nginx的跨域、alias、优化
    HTTP基础知识
    项目问题参考答案
  • 原文地址:https://blog.csdn.net/qq_51447496/article/details/128026008