Posted by lily's blog on May 9, 2025

数据库事务

参考文章:

  1. 一文详解脏读、不可重复读、幻读

数据库事务是一系列不可分割的操作的集合。数据库事务可以保证多个对数据的操作(一系列SQL语句)要么全部执行成功,要么全部不执行。

关系型数据库事务特性

ACID AID是手段,C是目的

并发事务会带来的问题

  1. 脏读
  2. 丢失修改(Lost to Modify)
  3. 不可重复读
  4. 幻读

    不可重复读与幻读

不可重复读: 强调的是在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据出现不一致的情况。

幻读: 并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读。

如何在RR下解决幻读

在不可重复读中另一个事务会用到delete和update语句,mysql中可以使用Record lock记录锁来对要修改的记录进行事务管理。当另一个事务需要插入数据,使用insert语句时,由于Record lock只能锁住已存在的记录,为了避免插入新数据带来的并发问题,需要依赖间隙锁(gap lock),所以在执行insert的时候需要依赖Next-key lock(Record lock和gap lock)来保证不会出现幻读。

![[Pasted image 20241023180643.png]]

并发事务的控制方式

在mysql中

    1. 读锁
    2. 写锁
    3. 意向锁
    4. 插入意向锁
    5. 独占锁
    6. 共享锁
    7. 记录锁
    8. 间隙锁
    9. 临键锁
  1. MVCC
    1. read view
    2. undo log

      事务隔离级别

  2. 读未提交(read-uncommited):读未提交的数据,可能会导致脏读,幻读,不可重复读。
  3. 读已提交(read-commited): 允许读取已经提交的数据,但是还是会导致幻读,不可重复读。
  4. 可重复读(repeatable-read):保证对同一字段的多次读取结果都是一致的,除非被自己的事务修改,但是还是不能解决幻读。其实RR解决的是不可重复读,能否解决幻读还需要看select语句时是否使用Next-key lock来锁住查询记录。
  5. 可串行化(Serializable):多个事务依次处理,最高的隔离级别,完全符合ACID特性,但是性能比较低。

参考文章:

  1. MVCC详解

    MVCC

MVCC实现

实例

MVCC是否解决幻读

RR解决幻读依靠的是锁机制,而不是MVCC机制 在RC级别下每一次select都会新生成一个readview,也就是当前维护的readview列表会被重新生成,当前事务版本号会变成最新事务版本号,意味着对于每次select来说都类似于开启了一段新的事务,因此可以select到当前最新的undo log记录