_事物_事物四大特征ACID&事物的隔离级别

  • 事物四大特征ACID

1.原子性(Atomicity)
每个事务都是一个整体,不可再拆分,事务中所有的 SQL 语句要么都执行成功,要么都失败。

2.一致性(Consistency)
事务在执行前数据库的状态与执行后数据库的状态保持一致。如:转账前2个人的总金额是 2000,转账后 2 个人总金额也是 2000

3.隔离性(Isolation)
事务与事务之间不应该相互影响,执行时保持隔离的状态。

4.持久性(Durability)
一旦事务执行成功,对数据库的修改是持久的。就算关机,也是保存下来的。

  • 事物的隔离级别

  • 概念:
    多个事务之间隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。

  • 存在问题:

    • 1. 脏读:
      一个事务,读取到另一个事务中没有提交的数据
    • 2. 不可重复读(虚读):
      在同一个事务中,两次读取到的数据不一样。要求的是一个事务中多次读取时数据是一致的,这是事务 update 时引发的问题
    • 3. 幻读:
      一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。这是 insert 或 delete 时引发的问题
  • 隔离级别:
    1. read uncommitted:读未提交
    * 产生的问题:脏读、不可重复读、幻读
    2. read committed:读已提交 (Oracle)
    * 产生的问题:不可重复读、幻读
    3. repeatable read:可重复读 (MySQL默认)
    * 产生的问题:幻读
    4. serializable:串行化
    * 可以解决所有的问题

      	* 注意:隔离级别从小到大安全性越来越高,但是效率越来越低
      	* 数据库查询隔离级别:
      		* select @@tx_isolation;
      	* 数据库设置隔离级别:
      		* set global transaction isolation level  级别字符串;
    

数据库查询隔离级别:
* select @@tx_isolation;
* mysql8.0之后用select @@transaction_isolation;
数据库设置隔离级别:
* set global transaction isolation level 级别字符串;

  • 事物的隔离级别演示

  • 1.脏读的演示
    将数据进行恢复:UPDATE account SET balance = 1000;

    1. 打开 A 窗口登录 MySQL,设置全局的隔离级别为最低
      在这里插入图片描述
    2. 打开 B 窗口,AB 窗口都开启事务

    在这里插入图片描述

    1. A 窗口更新 2 个人的账户数据,未提交
      并查询。在这里插入图片描述
  1. B 窗口查询账户
    发现读取到了另一个事物未提交的数据。

在这里插入图片描述
5. A 窗口回滚,B窗口查询数据,发现钱没了。
在这里插入图片描述

脏读是非常危险的,比如张三向李四购买商品,张三开启事务,向李四账号转入 500 块,然后打电话给李四说钱已经转了。李四一查询钱到账了,发货给张三。张三收到货后回滚事务,李四的再查看钱没了。

  • 解决脏读的问题:
    将全局的隔离级别进行提升
    在 A 窗口设置全局的隔离级别为 read committed,继续如上操作
    这次B窗口在此查询数据,发现并没有读取到另一个事物未提交的数据。
    在这里插入图片描述
    A 窗口 commit 提交事务,B 窗口查看账户
    在这里插入图片描述
    结论:read committed 的方式可以避免脏读的发生
  • 2.不可重复读的演示
    1.将数据进行恢复后,开启A窗口,设置数据库查询隔离级别为read committed

在这里插入图片描述
2.开启A,B窗口事物,在A窗口更新数据,继续在B窗口查询数据,会发现两次查询的数据不一致。
在这里插入图片描述
两次查询输出的结果不同,到底哪次是对的?不知道以哪次为准。 很多人认为这种情况就对了,无须困惑,当然是后面的为准。我们可以考虑这样一种情况,比如银行程序需要将查询结果分别输出到电脑屏幕和发短信给客户,结果在一个事务中针对不同的输出目的地进行的两次查询不一致,导致文件和屏幕中的结果不一致,银行工作人员就不知道以哪个为准了。

  • 解决不可重复读的问题:
    将全局的隔离级别进行提升为:repeatable read
    将数据进行恢复。

    1. A 窗口设置隔离级别为:repeatable read
    2. B 窗口退出 MySQL,B 窗口再进入 MySQL
    3. A 窗口更新数据
    4. B 窗口查询

    在这里插入图片描述

  • 3.幻读的演示

在 MySQL 中无法看到幻读的效果。
但我们可以将事务隔离级别设置到最高,以挡住幻读的发生 将数据进行恢复。
1.开启 A 窗口,将事务隔离级别设置到最高后,A窗口退出 MySQL
在这里插入图片描述

2.打开A,B窗口,开启事务。
3.在A窗口进行转账操作,B窗口进行查询,会发现B窗口查询无法执行,只有光标一直在闪烁,相当于这张表被锁起来了。

在这里插入图片描述

4.在 A 窗口中 commit 提交事务,B 窗口中 insert 语句会在 A 窗口事务提交后立马运行。

在这里插入图片描述
结论:使用 serializable 隔离级别,一个事务没有执行完,其他事务的 SQL 执行不了,可以挡住幻读

猜你喜欢

转载自blog.csdn.net/weixin_44664432/article/details/109363487