MySQL事务隔离级别

不积跬步,无以至千里;不积小流,无以成江海

事务的概念

  • 数据库事务是访问并可能更新数据库中各种数据项的一个程序执行单元

事务的组成

  • 一个数据库事务通常包含对数据库进行读或写的一个操作序列
一个典型的数据库事务:
BEGIN TRANSACTION //事务开始 
SQL1
SQL2
COMMIT/ROLLBACK  //事务提交或回滚 

事务的相关特性

  1. 数据库事务可以包含一个或多个数据库操作,但这些操作构成一个逻辑上的整体。
  2. 构成逻辑整体的这些数据库操作,要么全部执行成功,要么全部执行不成功。
  3. 构成事务的所有操作,要么全都对数据库产生影响,要么全都不产生影响,即不管事务是否执行成功,数据库总能保持一致性状态。
  4. 以上即使在数据库出现故障以及并发事务存在的情况下依然成立。

事务的特性

原子性(Atomicity)

  • 事务中的所有操作作为一个整体像原子一样不可分割,要么全部成功,要么全部失败。

一致性(Consistency)

  • 事务的执行结果必须使数据库从一个一致性状态到另一个一致性状态。

隔离性(Isolation)

  • 并发执行的事务不会相互影响,其对数据库的影响和它们串行执行时一样。

持久性(durability)

  • 事务一旦提交,其对数据库的更新就是持久的。任何事务或系统故障都不会导致数据丢失。

事务并发异常

  1. 丢失更新
    指事务覆盖了其他事务对数据的已提交修改,导致其他事务的修改好像丢失了一样

  2. 脏读
    指一个事务读取了另一个事务未提交的数据

  3. 幻读
    指事务读取某个范围的数据时,因为其他事务的操作导致前后两次读取的结果不一致

  4. 不可重复读
    指一个事务对同一数据的读取结果前后不一致

事务的隔离级别

概念:事务并发操作同一批数据的时候所导致的问题可以通过设置隔离级别来解决。

隔离级别的分类(由低到高)

  • 读未提交(READ UNCOMMITTED)
  • 读已提交 (READ COMMITTED) – Oracle默认级别
  • 可重复度(REPEATABLE READ) – MySQL默认级别
  • 串行化(SERIALIZABLE)

隔离级别从小到大安全性越来越高,但是效率越来越低

丢失更新

  • 如果多个线程操作,基于同一个查询结构对表中的记录进行修改,那么后修改的记录将会覆盖前面修改的记录,前面的修改就丢失掉了,这就叫做更新丢失。

解决办法
丢失更新解决办法
丢失更新举例

MySQL事务隔离级别演示

创建account表
CREATE TABLEaccount(idint(11) NOT NULL AUTO_INCREMENT,namevarchar(32) COLLATE utf8_bin DEFAULT NULL,balancedouble DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

初始化数据
初始化数据

演示-----读未提交

在这里插入图片描述

脏读

开启命令界面
开启命令界面
查询MySQL版本
查询MySQL版本
查看当前事务隔离级别
当前事务隔离级别
设置当前隔离级别为读未提交
设置为读未提交
开启另一个命令界面,同样查看隔离级别并设置为读未提交
另一个命令界面
分别在两个命令界面查询id为1的记录,name为张三的余额都为1000,并开启事务。
在这里插入图片描述
此时在命令界面A修改余额为500,并查询结果。
在这里插入图片描述
然后在命令界面B查询id为1的结果也为500,此时说明在事务A并未提交的情况下出现了脏数据,说明在读未提交的隔离级别下会发生脏读问题。
在这里插入图片描述

不可重复读

不可重复读
同时在命令界面A、B开始事务。
命令界面A查询张三的余额为1000
在这里插入图片描述
命令界面B查询张三的余额也为1000
在这里插入图片描述
在命令界面A设置余额为900,并提交事务
在这里插入图片描述
最后在命令界面B再次查询结果为900,这时在同一个事务中两次查询的结果不一致,说明在读未提交下会出现不可重复读问题。
在这里插入图片描述

幻读

幻读
同时在命令界面A、B开始事务。
命令界面A查询总余额为2900
在这里插入图片描述
在命令界面B新增一个名为赵六的账户,并设置余额为1000,提交事务
在这里插入图片描述
提交成功后在命令界面A中查询总余额,此时结果为3900,跟之前的总余额不一样了,这就是属于两次统计总余额发生不一致,前面的统计就像是虚幻的一样。说明在读未提交下会出现幻读的问题。
在这里插入图片描述

演示-----读已提交

读已提交

脏读

打开两个命令界面A、B,分别设置事务隔离级别为读已提交,并开启事务。
首先在界面A查看id为1的余额为1000,然后修改余额为900,不提交事务。
在这里插入图片描述
然后,在界面B中查看id为1的余额为1000,此时读取到仍然是A事务修改之前的内容,这就说明读已提交不存在脏读的问题。
在这里插入图片描述

不可重复读

在命令界面A、B中分别开启事务
首先在界面A查询id为1的余额为1000
在这里插入图片描述
然后,在界面B修改id为1的余额为800,并提交事务
在这里插入图片描述
最后,在界面A再次查看id为1的余额变为了800,此时说明在读已提交的隔离级别下依旧存在不可重复读的问题。
在这里插入图片描述

幻读

同时在命令界面A、B开始事务。
命令界面A查询总余额为3800
在这里插入图片描述
在命令界面B新增一条数据,并设置余额为1000,提交事务
在这里插入图片描述
提交成功后在命令界面A中查询总余额,此时结果为4800,跟之前的总余额不一样了,这就说明读已提交下依旧存在幻读的问题。
在这里插入图片描述

演示-----可重复读

在这里插入图片描述

脏读

分别在命令界面A、B设置隔离级别为可重复度,并开启事务。首先在界面A查询id为1的余额为800,然后修改余额为1000,最后在界面B查询的结果为事务A修改前的结果,说明脏读在可重复读的隔离级别下不存在。
在这里插入图片描述
在这里插入图片描述

不可重复读

分别在命令界面A、B开启事务。首先在界面A查询id为1的余额为1000,然后在界面B修改余额为500并提交事务,最后在界面A查询id为1的结果依然为1000,说明不可重复读在可重复读的隔离级别下不存在。
界面A:
在这里插入图片描述
界面B:
在这里插入图片描述

幻读

分别在命令界面A、B开启事务。首先在界面A查询总余额为4500,然后在界面B添加一条余额为1000的记录并提交事务,之后在界面A再次查询总余额结果依然为4500,此时,并没有出现幻读的情况,理论上可重重复读的隔离级别是不能防幻读的,但是因为,可重复读会对读的行来加锁,导致其他的事务修改不了这条数据,直到这个事务结束。但是,这种方案只能锁住数据行,也就是说如果有新的数据进来是阻止不了的,这也就是产生幻读的原因。但是,像MySQL、Oracle等这些成熟的数据库,它们不会采用这种影响性能的方案,所以在可重复读的这种隔离级别下就已经解决了幻读出现的问题。

演示-----可串行化

在这里插入图片描述
一旦设置隔离级别为可串行化,所有的异常都不会出现,但是它的效率最低,不推荐使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

予润

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值