• MySQL事务



    MySQL事务

    一、事务介绍

    什么是事务

    一个事务是一个完整的业务逻辑单元,不可再分。

    比如:银行账户转账,从A账户向B账户转账10000.需要执行两条update语句:
    update t_act set balance = balance - 10000 where actno = ‘act-001’;
    update t_act set balance = balance + 10000 where actno = ‘act-002’;

    以上两条DML语句必须同时成功,或者同时失败,不允许出现一条成功,一条失败。

    要想保证以上的两条DML语句同时成功或者同时失败,那么就需要使用数据库的“事务机制”。

    应用场景

    事物的和事务相关的语句只有DML语句。(insert delete update)—— 事务之和对数据产生变化的操作有关
    为什么?因为它们这三个语句都是和数据库表当中的“数据”相关的。
    事务的存在是为了保证数据的完整性,安全性。

    如果只有一条DML语句,还需要事务机制嘛?

    不需要!

    但实际情况不是这样的,通常一个“事儿(事务【业务】)”需要多条DML语句共同联合完成。

    综上所述:事务机制就是在处理某一个业务(事务)时多条DML语句同时成功或者同时失败,保证数据的完整性,安全性

    事务如何实现

    事务如何做到多条DML语句同时成功或者同时失败?

    MySQL中的InnoDB存储引擎:提供了一组用来记录事务活动的日志文件(log)

    事务开启了!

    insert

    insert

    update

    delete

    事务结束了!

    在事务执行的1过程中,每一条DML语句都会记录到事务性活动的日志文件中,在事务的执行过程中,我们可以提交事务,也可以回滚事务。

    提交事务?

    提交事务,就会清空事务性活动的日志文件,将数据全部彻底持久化到数据库表中。

    提交事务标志着,事务的结束!并且是一种全部成功(所有DML全部成功)的结束

    事务回滚?

    将之前的所有DML全部撤销,并且清空事务性活动的日志文件。

    回滚事务,标志着事物的结束!并且是一种全部失败(所有DML全部失败)的结束

    怎么提交和回滚事务

    • 事务提交:commit
    • 事务回滚:rollback ——(回滚到上一次commit的地方)

    测试:MySQL中的事务默认提交方式是怎么样的?手动提交还是自动提交呢?——自动提交

    ​ 自动提交?—— 没执行一条DML语句,就会提交一次事务

    在这里插入图片描述

    上述我们删除表中的数据后,进行回滚,并不能将原来的数据恢复,那是因为,在执行delete语句后,事务自动提交(默认),然后就会清空事务性活动的日志文件,当进行回滚时无法从日志文件中拿到并恢复数据!

    这种自动提交实际是不符合我们的开发习惯的,因为一个业务通常需要多条DML语句共同执行完成的,为了保证数据的安全,必须要求同时成功完成后再进行提交,所以不能执行一条就提交一条!

    我们如何关闭MySQL的默认自动提交事务,而是自己手动提交事务呢?

    关闭自动提交事务命令(我们自己开启事务),先执行这一条命令:start transaction

    然后就是DML语句

    最后提交事务

    事务回滚:

    在这里插入图片描述

    提交事务与回滚事务:滚不回去了!

    在这里插入图片描述

    二、事务的特性

    一个事务就是完成一件事(一个完整的业务逻辑)

    事务有四大特性:ACID

    • A:原子性:事务是最小的工作单元,不可再分。
    • C:一致性:事务必须保证多条DML语句同时成功或者同时失败。
    • I:隔离性:事务A与事务B之间具有隔离。
    • D:持久性:持久性说的是最终数据必须持久化到硬盘文件中,事务才算成功的结束。(真正存到数据库中)

    三、事务的隔离性即演示

    1. 隔离性的4个级别

    事务隔离性存在隔离级别,理论上隔离级别包括4个:

    • 第一级别:读未提交(read uncommitted
      对方事务还没有提交,我们当前事务可以读取到对方未提交的数据。
      读未提交存在脏读(Dirty Read)现象:表示读到了脏的数据。
    • 第二级别:读已提交(read committed)
      对方事务提交之后的数据我方可以读取到。
      这种隔离级别解决了: 脏读现象没有了。
      读已提交存在的问题是:不可重复读。
    • 第三级别:可重复读(repeatable read)————(MySQL默认的事务隔离级别)
      这种隔离级别解决了:不可重复读问题。
      这种隔离级别存在的问题是:读取到的数据是幻象。
    • 第四级别:序列化读/串行化读(serializable)
      解决了所有问题。
      效率低。需要事务排队。

    MySQL命令行的默认配置中事务都是自动提交的,即执行SQL语句就会马上执行COMMIT操作。可以用命令START TRANSACTION开始一个事务。

    我们可以通过下面命令设置事务隔离级别。

    SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]
    
    • 1
    1级别:读未提交
    	set global transaction isolation level read uncommitted;2级别:读已提交
    	set global transaction isolation level read committed;3级别:可重复读
    	set global transaction isolation level repeatable read;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    cd C:\Program Files\MySQL\MySQL Server 8.0\bin
    
    • 1

    查看当前事务级别:

    select @@transaction_isolation;
    
    • 1

    我们再来看一下我们在实际操作中使用到的一些并发控制语句:

    • START TRANSACTION | BEGIN :显示的开启一个事务。
    • COMMIT:提交事务,使得对数据库做的所有修改成为永久性。
    • ROLLBACK:回滚到结束用户的事务,并撤销正在进行的所有未提交的修改。

    2.隔离性演示

    (1)第一级别

    第一级别:读未提交(read uncommitted
    对方事务还没有提交,我们当前事务可以读取到对方未提交的数据。
    读未提交存在脏读(Dirty Read)现象:表示读到了脏的数据。

    事务A--------------------------------------事务B

    窗口A和窗口B并行进行测试检验!

    1、在窗口A将全局事务级别设为 read uncommitted

    	set global transaction isolation level read uncommitted;
    
    • 1

    成功,退出,再进入

    查看级别等级——设置成功

    select @@transaction_isolation;
    
    • 1

    在这里插入图片描述

    2、同时开两个命令窗口,登录数据库,进入到我们测试用的数据库

    窗口A:

    1、开启事务

    start transaction;
    
    • 1

    2、查一下数据

    select * from user;
    
    # 表此时为空
    
    • 1
    • 2
    • 3

    窗口B:

    1、开启事务

    start transaction;
    
    • 1

    2、插入数据(未提交(事务未提交,没有commit))

    insert into user values("张三");
    
    • 1

    再回到窗口A:查看数据,发现数据查出来了!!!

    在这里插入图片描述

    第一级别:

    第一级别:读未提交(read uncommitted
    对方事务还没有提交,我们当前事务可以读取到对方未提交的数据。

    (2)第二级别

    事务A--------------------------------------事务B

    窗口A和窗口B并行进行测试检验!

    1、在窗口A将全局事务级别设为 read committed

    	set global transaction isolation level read committed;
    
    • 1

    成功,退出,再进入

    查看级别等级——设置成功

    select @@transaction_isolation;
    
    • 1

    在这里插入图片描述

    2、同时开两个命令窗口,登录数据库,进入到我们测试用的数据库

    窗口A:

    1、开启事务

    start transaction;
    
    • 1

    2、查一下数据

    select * from user;
    
    # 表此时为空
    
    • 1
    • 2
    • 3

    窗口B:

    1、开启事务

    start transaction;
    
    • 1

    2、插入数据(未提交(事务未提交,没有commit))

    insert into user values("李四");
    
    • 1

    3、再回到窗口A:查看数据,数据未查出来!!!

    在这里插入图片描述

    4、回到窗口B,进行事务提交

    commit;
    
    • 1

    ​ 5、再回到窗口A:查看数据,数据查出来了!!!

    在这里插入图片描述

    第二级别

    1第二级别:读已提交(read committed)
    对方事务提交之后的数据我方可以读取到。
    这种隔离级别解决了: 脏读现象没有了。
    读已提交存在的问题是:不可重复读。

    (3)第三级别

    事务A--------------------------------------事务B

    窗口A和窗口B并行进行测试检验!

    1、在窗口A将全局事务级别设为 repeatable read

    	set global transaction isolation level repeatable read;
    
    • 1

    成功,退出,再登录进入

    查看级别等级——设置成功

    select @@transaction_isolation;
    
    • 1

    在这里插入图片描述

    2、同时开两个命令窗口,登录数据库,进入到我们测试用的数据库

    窗口A:

    我们事先先插入一条数据:

    insert into user values("6666");
    
    • 1

    1、开启事务

    start transaction;
    
    • 1

    2、查一下数据

    select * from user;
    
    # 表此时有一条数据6666
    
    • 1
    • 2
    • 3

    窗口B:

    1、开启事务

    start transaction;
    
    • 1

    2、插入数据(未提交(事务未提交,没有commit))

    insert into user values("李四");
    insert into user values("李四");
    insert into user values("李四");
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    4、提交事务

    commit;
    
    • 1

    窗口A:

    5、再回到窗口A:查看数据,数据未查出来!!!

    在这里插入图片描述

    6、窗口A中,提交事务后,就可以看到新数据了

    在这里插入图片描述

    1第三级别:可重复读(repeatable read)
    这种隔离级别解决了:不可重复读问题。
    这种隔离级别存在的问题是:读取到的数据是幻象。

    总结:两个事务是独立的,当对同一张表同时开启事务,事务B中进行DML语句,commit结束事务B后,只要事务A此时还没结束,那么A事务中查询到的数据都是事务B提交前的数据(两个事务同时进行时,事务独立开来了,互不影响的(第三级别)),只有当事务Acommit后,事务B中的DML语句产生的影响才会作用到事务A,此时查询到的数据是更新后的!

    (4)第四级别

    窗口A和窗口B并行进行测试检验!

    1、在窗口A将全局事务级别设为 serializable

    	set global transaction isolation level serializable;
    
    • 1

    成功,退出,再进入

    查看级别等级——设置成功

    select @@transaction_isolation;
    
    • 1

    在这里插入图片描述

    2、同时开两个命令窗口,登录数据库,进入到我们测试用的数据库

    窗口A:

    1、开启事务

    start transaction;
    
    • 1

    2、查一下数据

    select * from user;
    
    # 表此时为空
    
    • 1
    • 2
    • 3

    3、插入数据(未提交(事务未提交,没有commit)—— 事务A没结束)

    insert into user values("张三");
    
    • 1

    窗口B:

    1、开启事务(事务要同时开启的)

    start transaction;
    
    • 1

    2、查询数据,发现窗口B,光标卡住了

    因为两个事务同时操作这张表了,第四级别四需要排队的!!!

    在这里插入图片描述

    窗口A:

    再回到窗口A:结束事务——发现窗口B立即查出数据来了(说明第四级别事务需要排队!!!!)

  • 相关阅读:
    域前置通信过程和溯源思路
    京东商品接口加解密算法解析
    【Azure 架构师学习笔记】-Azure Data Factory (5) --Data Flow
    信息学奥赛一本通:1155:回文三位数
    力扣第18题 四数之和 c++双指针注释版。
    企微SCRM营销平台MarketGo-ChatGPT助力私域运营
    呼吸道合胞病毒(RSV)介绍
    Guli商城-商品服务-API-三级分类-配置网关路由与路径重写
    Redis面试问题三什么是缓存雪崩怎么解决
    webpack 静态资源文件加载(assets)
  • 原文地址:https://blog.csdn.net/qq_54773252/article/details/127585017