在关系型数据库管理系统中,一个逻辑工作单元要成为事务,必须满足这 4 个特性,即所谓的 ACID:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。
1)原子性
原子性:事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
InnoDB存储引擎提供了两种事务日志:redo log(重做日志)和undo log(回滚日志)。其中redo log用于保证事务持久性;undo log则是事务原子性和隔离性实现的基础。
每写一个事务,都会修改Buffer Pool,从而产生相应的Redo/Undo日志:
实现原子性的关键,是当事务回滚时能够撤销所有已经成功执行的sql语句。
InnoDB 实现回滚,靠的是undo log :当事务对数据库进行修改时,InnoDB 会生成对应的undo log ;如果事务执行失败或调用了rollback ,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。
2)一致性
一致性:事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
3)隔离性
隔离性:指的是一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对其他的并发事务是隔离的。
不考虑隔离性会引发的问题:
数据库事务的隔离级别有4个,由低到高依次为Read uncommitted 、Read committed、Repeatable read 、Serializable ,这四个级别可以逐个解决脏读 、不可重复读 、幻读 这几类问题。
4)持久性
持久性:指的是一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,后续的操作或故障不应该对其有任何影响,不会丢失。
MySQL 事务的持久性保证依赖的日志文件: redo log
5)ACID总结
可重复读(repeatable read)定义: 一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。
MVCC
Undo log 多版本链
每条数据都有两个隐藏字段:
每一条数据都有多个版本,版本之间通过undo log链条进行连接通过这样的设计方式,可以保证每个事务提交的时候,一旦需要回滚操作,可以保证同一个事务只能读取到比当前版本更早提交的值,不能看到更晚提交的值。
ReadView
Read View是 InnoDB 在实现 MVCC 时用到的一致性读视图,即 consistent read view,用于支持 RC(Read Committed,读提交)和 RR(Repeatable Read,可重复读)隔离级别的实现.
Read View简单理解就是对数据在某个时刻的状态拍成照片记录下来。那么之后获取某时刻的数据时就还是原来的照片上的数据,是不会变的.
Read View中比较重要的字段有4个:
m_ids
: 用来表示MySQL中哪些事务正在执行,但是没有提交.min_trx_id
: 就是m_ids里最小的值.max_trx_id
: 下一个要生成的事务id值,也就是最大事务idcreator_trx_id
: 就是你这个事务的id当一个事务第一次执行查询sql时,会生成一致性视图 read-view(快照),查询时从 undo log 中最新的一条记录开始跟 read-view 做对比,如果不符合比较规则,就根据回滚指针回滚到上一条记录继续比较,直到得到符合比较条件的查询结果。
Read View判断记录某个版本是否可见的规则如下
1.如果当前记录的事务id落在绿色部分(trx_id < min_id),表示这个版本是已提交的事务生成的,可读。
2.如果当前记录的事务id落在红色部分(trx_id > max_id),表示这个版本是由将来启动的事务生成的,不可读。
如果当前记录的事务id落在黄色部分(min_id <= trx_id <= max_id),则分为两种情况:
若当前记录的事务id在未提交事务的数组中,则此条记录不可读;
若当前记录的事务id不在未提交事务的数组中,则此条记录可读。