文章目录
- 1.事务介绍
- 2 事务特性
- 3. 事务的实现原理
- 4 redo log 保证持久性
- 5 undo log 保证原子性
- 6 MVCC 概念
- 6.1 隐藏字段
- 6.2 版本链
- 6.3 ReadView
- 6.3.1readview 版本控制规则
- 7 隔离性 实现
- 7.2 隔离性- REPEATABLE READ 可重复读下
- 8 一致性
1.事务介绍
事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时袋败
2 事务特性
- 原子性(Atomicity): 事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
- 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
- 隔离性(lsolation): 数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的-独立环境下运行
- 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
3. 事务的实现原理
原子性、一致性、持久性主要是通过 redo.log 日志和 undo.logo日志实现的
隔离性 根据锁和MVCC(多版本控制)实现
4 redo log 保证持久性
重做日志:记录的是事务提交时数据页的物理修改,是用来实现事务的持久性
。该日志文件由两部分组成:重做日志缓冲
(redo log buffer)以及重做日志文件
(redo log fle),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都存到该日志文件中,用于在刷新脏页到磁盘,发生错误时,进行数据恢复使用
。
当事务提交时,首先从 ibd文件中io需要更改的数据到 内存中的buffer pool ,在buffer pool中进行数据修改,同时把数据页变化加载到redo log buffer中 ,然后redo log buffer 通过顺序io的方式,刷新到磁盘中的redo log fle文件(增加日志速度更快),即完成事务的提交 ,随后 buffer pool 将随机刷新,将更改后的数据刷新到ibd中,随后如果出现发生crash,则重新读取redo log fle 到buffer pool 完成持久化。
idb 为mysql 存储数据的物理文件
当buffer pool中的dirty page 还没有刷新到磁盘的时候,发生crash,启动服务后,可通过redo log 找到需要重新刷新到磁盘文件的记录;
buffer pool中的数据直接flush到disk file,是一个随机IO,效率较差,而把buffer pool中的数据记录到redo log,是一个顺序IO,可以提高事务提交的速度;
5 undo log 保证原子性
回滚日志,用于记录数据被修改前的信息,作用包含两个:提供回滚
和 MVCC(多版本并发控制)
。undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undolog中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。当执行rolback时,就可以从undo og中的逻辑记录读取到相应的内容并进行回滚。
- Undo log销毁: undo log在事务执行时产生,事务提交时,并不会立即删除undo log,因为这些日志可能还用于MVCC。
- Undo log存储:undo log采用段的方式进行管理和记录,存放 是rollback segment回滚段中,内部包含1024个undo loosegment.
6 MVCC 概念
MVCC 全称 Multi-Version (oncurrencyontrol,多版本并发控制。指维护个数据的多个版本,使得读写操作没有冲突,快照读为MySQL实现MVCC提供了一个非阻塞读功能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView。
- 当前读
读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如:select… lockin share mode(共享锁),select … for update、 update、insert、delete(排他锁)都是一种当前读
- 快照读
简单的select(不加锁)就是快照读,快照读,读取的是记录数据的可见版本,有可能是历史数据,不加锁,是非阻塞读。
不同隔离级别下的快照读
- Read Committed:每次select,都生成一个快照读。
- Repeatable Read:开启事务后第一个select语句才是快照读的地方
- Serializable:快照读会退化为当前读。
6.1 隐藏字段
在数据库表中除了有 表的属性,还有三个隐藏字段
隐藏字段 | 含义 |
---|---|
DB TRX ID | 最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID。 |
DB ROLL PTR | 回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。 |
DB ROW ID | 隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。 |
6.2 版本链
不同事务或相同事务对同一条记录进行修改,会导致该记录的undolog生成一条记录版本链表,链表的头部是最新的旧记录,链表尾部是最
早的旧记录。
undo log记录存储情况
回滚日志,在insert、update、delete的时候产生的便于数据回滚的日志。
- insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除。
- update、delete的时候,产生的undolog日志不仅在回滚时需要,在快照读时也需要,不会立即被删除。
数据库表中隐藏字段 的DB ROLL PTR 列存储这上一个版数据 存 在undo log 中 。从而如同所示 undo log 中的数据形成一个版本链
6.3 ReadView
ReadView(读视图)是 快照读SOL执行时,MVCC提取数据的依据,记录并维护系统当前活跃的事务(未提交的)id。
字段 | 含义 |
---|---|
m_ids | 当前活跃的事务ID集合 |
min_trx_id | 最小活跃事务ID |
max_trx_id | 预分配事务ID,当前最大事务ID+1(因为事务ID是自增的) |
creator_trx_id | ReadView创建者的事务ID |
6.3.1readview 版本控制规则
注意:当时事务id存储值 数据库表中 隐藏字段的 DB TRX ID 中
不同的隔离级别,生成Readview的时机不同:
READ COMMITTED : 在事务中每一次执行快照读时生成ReadView。
REPEATABLE READ: 仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。
7 隔离性 实现
##7.1 隔离性 -读已提交 原理
READ COMMITTED : 在事务中每一次执行快照读时生成ReadView,我们根据ReadView 和undo log ,确定查询的是那条记录
如图所示 事务5 第一次查询时 生成的readVive 根据版本控制规则 ,DB_ROLL_PIR 为DX0003的记录进行匹配 发现不满足版本控制规则,则对undo log 中的下一条记录进行匹配,发现也不满足,继续匹配下一规则,发现满足 第二个规则,查询时则会展示 这条记录。
7.2 隔离性- REPEATABLE READ 可重复读下
可重复读下 流程和RC 模式相同只是在第一次查询时生成快照读 剩下的全部复用第一次的快照读。