跳到主要内容

MySQL事务总结

参考:https://xiaolincoding.com/mysql/transaction/mvcc.html#%E4%BA%8B%E5%8A%A1%E6%9C%89%E5%93%AA%E4%BA%9B%E7%89%B9%E6%80%A7

事务的特性ACID

InnoDB 引擎支持事务,MyISAM 引擎不支持事务

事务的四个特性:

  • 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
  • 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
  • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。

实现:

  • 原子性:通过 undolog 来实现。
  • 持久性:通过 binlog、redolog 来实现。
  • 隔离性:通过(读写锁+MVCC)来实现。
  • 一致性:MySQL 通过原子性、持久性、隔离性最终实现数据一致性。

对 MySQL 来说,逻辑备份日志(binlog)、重做日志(redolog)、回滚日志(undolog)、锁技术 + MVCC 就是 MySQL 实现事务的基础。

并发事务问题

问题描述
脏读一个事务读到另外一个事务还没有提交的数据。
不可重复读一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。
幻读一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在,好像出现了”幻影”。

事务的隔离级别:

  • 读未提交:一个事务还没提交时,它做的变更就能被其他事务看到;(脏读,不可重复读,幻读)
  • 读提交:一个事务提交之后,它做的变更才能被其他事务看到;(不可重复读,幻读)
  • 可重复读:指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,InnoDB 引擎的默认隔离级别,(幻读)
  • 串行化:会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;

幻读解决:

  • 针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好的避免幻读问题。
  • 针对当前读(select ... for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。

隔离级别的实现方式:

  • 读未提交:直接读
  • 读已提交:每个语句都生成一个ReadView
  • 可重复读:启动事务生成一个ReadView,整个事务期间都用
  • 串行化:读写锁

MVCC工作原理

多版本并发控制(MVCC):这是InnoDB存储引擎特有的一种机制,它可以在不加锁的情况下创建数据在某一时间点的快照。在读取数据时,MVCC会返回该时间点的数据版本,即使该数据后来被其他事务修改。这样,每个事务都有自己的数据视图,彼此之间不会互相影响,实现了隔离性。

四个字段

img

聚簇索引两个隐藏列:

图片

三种情况:

img

  • 如果记录的 trx_id 值小于 Read View 中的 min_trx_id 值,表示这个版本的记录是在创建 Read View 前已经提交的事务生成的,所以该版本的记录对当前事务可见。
  • 如果记录的 trx_id 值大于等于 Read View 中的 max_trx_id 值,表示这个版本的记录是在创建 Read View 后才启动的事务生成的,所以该版本的记录对当前事务不可见。
  • 如果记录的 trx_id 值在 Read View 的 min_trx_idmax_trx_id 之间,需要判断 trx_id 是否在 m_ids 列表中:
    • 如果记录的 trx_idm_ids 列表中,表示生成该版本记录的活跃事务依然活跃着(还没提交事务),所以该版本的记录对当前事务不可见。
    • 如果记录的 trx_id 不在 m_ids列表中,表示生成该版本记录的活跃事务已经被提交,所以该版本的记录对当前事务可见。

这种通过「版本链」来控制并发事务访问同一个记录时的行为就叫 MVCC(多版本并发控制)。