数据库笔记4---事务特性ACID、隔离级别、事务并发问题小结


一、什么是事务

  事务(Transaction)是指一组原子性的SQL操作,或者说是一个独立的工作单元,所有操作必须全部成功完成,如果其中有任何一条语句因为崩溃或其他原因无法执行,那么所有更改都会被撤消。可以通俗理解为:事务内的语句,要么全部执行成功,要么全部执行失败,即:“all-or-nothing” 。

  在MySQL中,事务支持是在存储引擎层实现的;并不是所有引擎都支持事务,如 MyISAM 就不支持,InnoDB 就支持。


二、事务的四个特性(ACID)

1. 原子性(Atomicity)

  一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部执行成功,要么全部失败回滚,回滚到执行指令前的数据状态。

2. 一致性(Consistency)

  事务的执行使数据库总是从一个一致性状态转换到另外一个一致性状态。

eg:拿转账来说,假设用户A和用户B两者的钱加起来一共是20000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是20000,这就是事务的一致性。

3. 隔离性(Isolation)

  隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。即:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。

通过上面的解释,我们能够理解什么是隔离性,不同的事务为了避免互相干扰必须互相隔离,甚至完全地串行执行,这样并发效率不高。所以SQL标准中定义了四种隔离级别(isolation level),每一种级别都规定了哪些是不可见的,哪些是事务内和事务间是可见的。通常较低级别的隔离可以执行更高的并发,系统的开销也更低。

4. 持久性(Durability)

  当事务正确完成后,它对于数据的改变是永久性的。此时即使系统崩溃,修改的数据也不会丢失。


三、隔离级别和并发问题

  在许多事务处理同一个数据时,如果没有采取适当的隔离级别,那么并发处理数据时,会带来一些的问题,即:脏读 、不可重复读 、幻读。

扫描二维码关注公众号,回复: 8771544 查看本文章

1.丢失更新

  • 第一类丢失更新
      由于某个事务的回滚操作,参与回滚的旧数据将其他事务的数据更新覆盖了。
时间序号 事务一 事务二
T1 开启事务 开启事务
T2 查询账户money=1000 查询账户money=1000
T3 存款100,money=1100
T4 转账100,money=900
T5 提交事务,money=900
T6 取消事务,回滚,money=1000
  • 第二类丢失更新
      一个事务提交时,把其他事务已提交的更新数据覆盖,造成之前其他事务提交的更新丢失。即:事务T1 和事务T2 从数据库中读入同一数据并修改。事务T1 先提交,执行完成,然后事务T2 提交后覆盖了事务T1 的提交的结果,导致事务T1 的修改丢失。
    在这里插入图片描述

2.脏读

  脏读(Dirty Read)是指在一个事务(T1)处理过程里读取了另一个未提交事务(T2)中的数据。如果事务(T2)由于某种原因被撤销,它修改过的数据恢复原值,那么事务(T1)读到的数据与数据库中的数据不一致,是不正确的数据,称作“脏”数据。
在这里插入图片描述

3.幻读(phantom read,也叫虚读)

  一个事务内执行两次查询,第二次结果集包含第一次中没有或某些行已经被删除的数据,造成两次结果不一致,只是另一个事务在这两次查询中间插入或删除了数据造成的。

在这里插入图片描述

4.不可重复读

  不可重复读,顾名思义,即在一个事务内 多次读取同一行数据时读出来的结果不一样。因为在读操作的中间正好有另一个事务更新了该行数据,导致两次读取的结果不一样,不可被信任。

案例:事务T1在读取某一行数据,而事务T2立马修改了这行数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发生了不可重复读。

注意点一:不可重复读和脏读的区别:脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。

注意点二:幻读和不可重复读有些类似。不可重复读关注的是对同一个数据项是否有update操作;幻读针对的是insert和delete,是对一批数据整体(比如数据的个数)。


四、事务的隔离级别

  事务的隔离级别有4种,由低到高分别为Read uncommitted 、Read committed 、Repeatable read 、Serializable 。不同的隔离级别有各自的特点:

√: 可能出现 ×: 不会出现

脏读 不可重复读 幻读
Read uncommitted
Read committed ×
Repeatable read × ×
Serializable × × ×

1. 未提交读(Read uncommitted)

  在Read uncommitted级别中,事务中的修改即使没有提交,对其他事务也是可见的。这个级别会导致很多问题,比如:脏读(Dirty Read)。性能上不必其他隔离级别好太多,但却缺乏其他级别的很多好处,所以在实际应用中一般很少使用。

2.提交读(Read committed)(可避免"脏读")

  • 大多数数据库系统的默认隔离级别都是Read committed(MySQL除外)。
  • 一个事务开始时,只能看到已经提交的事务所做的修改。即:一个事务从开始到提交前做的任何修改对其他事务都是不可见的。
  • 解决了“脏读”问题。
  • 无法避免“不可重复读”和“幻读”问题。执行两次同样的查询,可能会得到不一样的结果。

3.可重复读(Repeatable read)(可避免"脏读"、“不可重复读”)

  • MySQL中默认的隔离级别。
  • 该级别保证了同一个事务中多次读取同一条记录的结果是一致的。
  • 无法解决"幻读"。InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读问题。

4.串行化(Serializable )

  Serializable 是最高的隔离级别。它通过强制事务串行执行,可以避免脏读、不可重复读与幻读。实际应用中很少用到这个隔离级别。

注意事项:

  1. 大多数数据库默认的事务隔离级别是Read committed,但Mysql的默认隔离级别是Repeatable read。
  2. 隔离级别的设置只对当前链接有效。对于使用MySQL命令窗口而言,一个窗口就相当于一个链接,当前窗口设置的隔离级别只对当前窗口中的事务有效;对于JDBC操作数据库来说,一个Connection对象相当于一个链接,而对于Connection对象设置的隔离级别只对该Connection对象有效,与其他链接Connection对象无关。
  3. 设置数据库的隔离级别一定要是在开启事务之前。

五、参考资料

1、《高性能MySQL》
2、什么是事务?事务的四个特性以及事务的隔离级别
3、丢失更新,脏读,不可重复读,幻读

GNG
发布了118 篇原创文章 · 获赞 389 · 访问量 68万+

猜你喜欢

转载自blog.csdn.net/so_geili/article/details/100591190