事务

事务特性 #

  • 原子性 atomicity
  • 一致性 consistency
  • 隔离性 isolation
  • 持久性 durability

如何保证事务特性?

  • 持久性是通过 redo log (重做日志)来保证的;
  • 原子性是通过 undo log(回滚日志) 来保证的;
  • 隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;
  • 一致性则是通过持久性+原子性+隔离性来保证;

并发问题 #

脏读 #

如果一个事务「读到」了另一个「未提交事务修改过的数据」,就意味着发生了「脏读」现象

不可重复读 #

在一个事务内多次读取同一个数据,如果出现前后两次读到的数据不一样的情况,就意味着发生了「不可重复读」现象。

幻读 #

在一个事务内多次查询某个符合查询条件的「记录数量」,如果出现前后两次查询到的记录数量不一样的情况,就意味着发生了「幻读」现象。

事务隔离级别 #

read uncommitted 读未提及 #

可能发生脏读、不可重复读和幻读现象

read committed 读已提交 #

可能发生不可重复读和幻读现象

repeatable read 可重复读 #

可能发生幻读现象

MySQL InnoDB 引擎的默认隔离级别

serializable 串行化 #

MySQL InnoDB 引擎的默认隔离级别虽然是「可重复读」,但是它很大程度上避免幻读现象

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

MVCC #

multi-version concurrency control,多版本并发控制

隐式字段 #

对于InnoDB存储引擎,每一行记录都有两个隐藏列DB_TRX_ID、DB_ROLL_PTR,如果表中没有主键和非NULL唯一键时,则还会有第三个隐藏的主键列DB_ROW_ID

undo日志 #

快照读 #

读取的是记录数据的可见版本

当前读 #

读取的是记录数据的最新版本

Read View #

  • m_ids :指的是在创建 Read View 时,当前数据库中「活跃事务」的事务 id 列表,注意是一个列表,“活跃事务”指的就是,启动了但还没提交的事务。
  • min_trx_id :指的是在创建 Read View 时,当前数据库中「活跃事务」中事务 id 最小的事务,也就是 m_ids 的最小值。
  • max_trx_id :这个并不是 m_ids 的最大值,而是创建 Read View 时当前数据库中应该给下一个事务的 id 值,也就是全局事务中最大的事务 id 值 + 1;
  • creator_trx_id :指的是创建该 Read View 的事务的事务 id。