事务的隔离级别

本文详细介绍了数据库事务的ACID特性,包括原子性、一致性、隔离性和持久性,并探讨了事务的四种隔离级别——读未提交、读已提交、可重复读和可序列化,以及它们对脏读、不可重复读和幻读问题的解决方案。重点讨论了各隔离级别的优缺点和实际应用中的选择。最后,总结了事务隔离级别与数据库性能之间的平衡考虑。
摘要由CSDN通过智能技术生成


1.事务的基本要素(ACID)

  • 原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。
  • 一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。
  • 隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
  • 持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

2.事务的隔离级别

以Mysql数据库来分析四种隔离级别

  • 读未提交(Read uncommitted)
    "读事务"时,允许其他事务读和写该行数据。"写事务"时,禁止其他事务写该行数据,允许其他事务读该行数据。
    优点: 解决了"更新丢失"的问题。
    缺点: 可能出现"脏读"问题。描述:事务B读取到了事务A未提交的数据。

解决了:"更新丢失"问题,但是有"脏读"问题

  • 读已提交(Read committed)-Oracle默认
    "读事务"时,允许其他事务读和写该行数据。“写事务"时,禁止其他事务读和写该行数据。
    优点: 解决了"更新丢失"和"脏读"的问题。
    缺点: 可能出现"不可重复读”。描述:事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。一般同一个事务A里,查询指定条件的数据后,当前条件的数据紧接着被事务B更新了,当时事务A在用指定条件查询时就有可能查询不到数据了(比如:用指定条件更新数据,则数据就更新失败了)。
    使用的锁: “排他锁(写锁) + mvcc(多版本并发控制)”

解决了:"更新丢失"和"脏读"问题,但是有"不可重复读"问题

  • 可重复读取(Repeatable read)-Mysql默认
    读事务"时,允许其他事务读,禁止写该行数据。“写事务"时,禁止其他事务读和写该行数据。
    优点: 解决了"更新丢失”,“脏读"和"不可重复读"的问题。
    缺点: 可能出现"幻读(虚读)”。描述:事务A事先读取了数据,事务B紧接着新增了一条数据,并提交了事务,而事务A再次读取数据时,数据会多一条。"间隙锁"可解决幻读
    使用的锁: “共享锁(读锁) + 排他锁(写锁) + mvcc(多版本并发控制)”

解决了:“更新丢失”,"脏读"和"不可重复读"问题,但是有"幻读(虚读)"问题

  • 可序化(Serializable)
    提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行,如果仅仅通过“行级锁”是无法实现序列化的,必须通过其他机制保证新插入的数据不会被执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读

解决了更新丢失、脏读、不可重复读、幻读(虚读)

在这里插入图片描述

3.脏读、不可重复读和幻读的产生原因

  • 脏读(读取未提交的数据)
    一个事务读取另一个事务未提交的问题。脏读又称无效数据的读出,是指在数据库访问中,事务 A 对一个值做修改,事务 B 读取这个值,但是由于某种原因事务 A 回滚撤销了对这个值得修改,这就导致事务 B 读取到的值是无效数据。

  • 不可重复读(前后数据多次读取,结果集内容不一致)
    同一事务中,两次读取同一数据,得到内容不同。不可重复读即当事务 A 按照查询条件得到了一个结果集,这时事务 B 对事务 A 查询的结果集数据做了修改操作,之后事务 A 为了数据校验继续按照之前的查询条件得到的结果集与前一次查询不同,导致不可重复读取原始数据。
    可使用锁:“排他锁(写锁)”

  • 幻读(前后数据多次读取,结果集数量不一致)
    同一事务中,用同样的操作读取两次,得到的记录数不相同。幻读是指当事务 A 按照查询条件得到了一个结果集,这时事务 B 对事务 A 查询的结果集数据做新增操作,之后事务 A 继续按照之前的查询条件得到的结果集平白无故多了几条数据,好像出现了幻觉一样。

4.总结

  隔离级别最高的是"可序化(Serializable)"级别,最低的是"读未提交(Read uncommitted)"级别,当然级别越高,执行效率就越低,像"可序化(Serializable)"这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况来。

  • Mysql:默认的隔离级别是"可重复读取(Repeatable read)"。
  • Oracle:只支持"可序化(Serializable)"级别和"读已提交(Read committed)"这2种级别,其中默认的为"读已提交(Read committed)"级别
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值