MySQL事务的实现涉及到redo和undo以及purge,redo是保证事务的原子性和持久性;undo是保证事务的一致性(一致性读和多版本并发控制);purge清理undo表空间
背景知识,对于Innodb表中的行每一行包括:
6字节的事务ID(DB_TRX_ID)字段: 用来标识最近一次对本行记录做修改(INSERT|UPDATE)的事务的标识符, 即最后一次修改(INSERT|UPDATE)本行记录的事务id。
7字节的回滚指针(DB_ROLL_PTR)字段: 指写入回滚段(ROLLBACK segment)的 UNDO LOG record (撤销日志记录记录)。
如果一行记录被更新, 则 UNDO LOG record 包含 '重建该行记录被更新之前内容' 所必须的信息。
1,MySQL事务执行过程中,
对于undo log
对于update或者delete操作,每一行都保存了一个事务Id,修改事务Id为当前Session的事务id,
生成数据行事务之前的版本,将当前行的回滚指针指向事务之前的版本。
对于insert操作,将当前行的回滚指针指为空,因为insert没有事务操作之前的版本。
对于redo log
随着updatedeleteinsert操作的执行,重做日志Redo Log不断地写入重做日志缓存(redo_log_buffer),
对于Redo Log Buffer的落盘(写入 Redo Log File),有三种策略:
(1),事务commit的时候,
(2),redo_log_buffer(默认8MB)使用超过50%的时候,
(3),发生checkpoint的时候
也就是说,Redo Log Buffe的落盘并不一定是事务提交的时候才写入的,对于大事务,redo log是有可能逐步落盘的(2,3两点的影响)
2,事务的提交Commit
Redo Log Buffer的写盘,由变量innodb_flush_log_at_trx_commit决定,有三种模式分别是0,1,2
如果设置为0,事物提交不触发Redo Log Buffer写盘,每N秒将Redo Log Buffer的记录写入Redo Log文件,并且将Redo Log文件刷入硬件存储1次,N由innodb_flush_log_at_timeout控制。
如果设置为1,事务提交时同步刷新Redo Log Buffe到Redo Log文件,并且将Redo Log文件刷新到磁盘。
如果设置为2,事务提交时同步刷新Redo Log Buffe到Redo Log文件,.但是Redo Log 的flush(刷到磁盘)操作并不会同时进行。Redo Log的写盘由操作系统和innodb_flush_log_at_timeout控制。
需要注意的是,innodb_flush_log_at_trx_commit=1的情况下,尽管事务提交可以保证redo log同步写盘,
但是Redo Log Buffer的写盘并不一定只有在事务提交的时候才写入的,有可能是随着时候的执行(如果事务很大)逐步写盘的。
3,事务提之后
因为redo log的存在(写盘之后),事务的一致性和持久性得到了保证,对于内存中的脏数据,通过checkpoint或者内存机制刷入磁盘,在数据写入磁盘之后,redo log空间即可释放
对于undo log,当没有活动Session访问的时候,由purge线程异步清理undo log占用的空间
见不少人写博客使用xmind或者其他工具对相关知识点进行整理,
发现类似于xmind的结构图对于知识结构非常清晰,xmind第一份工作用过,好久没用了,装了试用版发现功能受限很多。
于是尝试类似于xmind的在线工具,发现百度脑图还可以,关键是在线的,随时随地就都可以打开整理相关的知识点。
参考:
https://segmentfault.com/a/1190000012650596
https://liuzhengyang.github.io/2017/04/18/innodb-mvcc/
MySQL技术内幕 InnoDB存储引擎