Undo 日志MySQL的MVCC(多版本并发控制)依赖Undo Log实现 。MySQL的表空间文件 t.ibd 存储的是记录最新值,每个记录都有一个回滚指针(见前面图中的Roll Ptr),指向该记录的最近一条Undo记录,而每条Undo记录都会指向它的前一条Undo记录,如下图所示 。默认情况下 undo log存储在系统表空间 ibdata1 中 。

文章插图
Undo Log示意图
CREATE TABLE `t3` ( `id` int(11) NOT NULL, `a` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;insert into t3 values(1, 'A');update t3 set a='B' where id=1;update t3 set a='C' where id=1;插入一条数据后,可以发现当前 t3.ibd 文件中的记录是 (1, ‘A’),而 Undo Log此时有一条 insert 的记录 。如下:root@stretch:/var/lib/mysql# innodb_space -s ibdata1 -T test/t3 -p 3 -R 127 record-historyTransaction Type Undo record(n/a) insert (id=1) → ()执行后面的update语句,可以看到 undo log如下:root@stretch:/var/lib/mysql# innodb_space -s ibdata1 -T test/t3 -p 3 -R 127 record-historyTransaction Type Undo record2333 update_existing (id=1) → (a="B")2330 update_existing (id=1) → (a="A")(n/a) insert (id=1) → ()需要注意的是,Undo Log 在事务执行过程中就会产生,事务提交后才会持久化,如果事务回滚了则Undo Log也会删除 。另外,删除记录并不会立即在表空间中删除该记录,而只是做个标记(delete-mark),真正的删除则是等由后台运行的 purge 进程处理 。除了每条记录有Undo Log的列表外,整个数据库也会有一个历史列表,purge 进程会根据该历史列表真正删除已经没有再被其他事务使用的 delete-mark 的记录 。purge 进程会删除该记录以及该记录的 Undo Log 。
双写缓冲先回顾下InnoDB的记录更新流程:先在Buffer Pool中更新,并将更新记录到 Redo Log 文件中,Buffer Pool中的记录会标记为脏数据并定期刷到磁盘 。由于InnoDB默认Page大小是16KB,而磁盘通常以扇区为单位写入,每次默认只能写入512个字节,无法保证16K数据可以原子的写入 。
如果写入过程发生故障(比如机器掉电或者操作系统崩溃),会出现页的部分写入(partial page writes),导致难以恢复 。因为 MySQL 的重做日志采用的是物理逻辑日志,即页间是物理信息,而页内是逻辑信息,在发生页部分写入时,无法确认数据页的具体修改而导致难以恢复 。
MySQL 的数据页在真正写入到表空间文件前,会先写到系统表空间文件的一段连续区域双写缓冲(Double-Write Buffer,默认大小为 2MB,128个页)并 fsync 落盘,等双写缓冲写入成功后才会将数据页写到实际表空间的位置 。
因为双写缓冲和数据页的写入时机不一致,如果在写入双写缓冲出错,可以直接丢弃该缓冲页,而如果是写入数据页时出错,则可以根据双写缓冲区数据恢复表空间文件 。
4、InnoDB 事务隔离级别InnoDB的多版本并发控制是基于事务隔离级别实现的,而事务隔离级别则是依托前面提到的 Undo Log 实现的 。当读取一个数据记录时,每个事务会使用一个读视图(Read View),读视图用于控制事务能读取到的记录的版本 。
InnoDB的事务隔离级别分为:Read UnCommitted,Read Committed,Repeatable Read以及Serializable 。其中Serializable是基于锁实现的串行化方式,严格来说不是事务可见性范畴 。
- Read Uncommitted:未提交读也称为脏读,它读取的是当前最新修改的记录,即便这个修改最后并未生效 。
- Read Committed:提交读 。它基于的是当前事务内的语句开始执行时的最大的事务ID 。如果其他事务修改同一个记录,在没有提交前,则该语句读取的记录还是不会变 。但是这种情况会产生不可重复读,即一个事务内多次读取同一条记录可能得到不同的结果(该记录被其他事务修改并提交了) 。
推荐阅读
- 喝什么样的花茶能养出女人好气色,花茶的感官鉴赏
- 喝什么花茶能减肥,喝玫瑰花茶有什么好处
- 喝山楂茶是能减肥的是吗,孕妇能喝菊花茶吗
- 菊花茶什么样的人不能喝,喝菊花茶的好处
- 喝玫瑰花茶能丰胸吗,孕妇能喝菊花茶吗
- 玫瑰花冠茶怎么泡,孕妇能喝玫瑰花茶吗
- 蒲公英和玫瑰花茶隔夜能喝吗,孕妇能喝玫瑰花茶吗
- 菊花茶去火吗,孕妇能喝菊花茶吗
- 过世的人的照片能留吗?
- 为什么说韭菜尽量少吃?
