MySQL的几种日志
MySQL主要有3种日志:
- 二进制日志,就我们都熟悉的
binlog
,它主要的作用 主从复制、PIT恢复 - 重做日志,redo log,它主要的作用是 当突然数据库宕机了,它能恢复数据
- 第三种就是 undo log,它主要用于事务回滚,以及事务中实现可重复读的功能
我们本篇主要说一说第三种 undo log 的作用以及实现
undo日志
它存放在共享表空间中的回滚段中,这是《InnoDB》书里面说记录 undo log 的时候也要写 redo log 的原因,因为它是在这个文件里面保存的。
- 一个回滚段有 1024 个 undo segment,数据库实例进程在 undo segment 中申请 undo 页来做操作
它对回滚的操作属于逻辑上回滚,不是物理回滚;一般会记录如下信息:
- 对于每一个 insert 操作,innodb 引擎会执行一个delete 操作;
- 对于 delete 操作,innondb 引擎会执行一个 insert 操作
- 对于 update 操作,会执行一个相反的 update 操作
事务提交后,不能马上删除 undo log 及 undo log 页,可能还有其他的事务通过 undo log 来得到行记录之前的版本。是否删除由 purge 线程来判断。
- Insert undo log 事务提交后可以直接删除
- Update undo log 记录对 delete、update 操作产生的 undo log,
上面那一段说不能直接删除,其实我有点蒙,在数据库里面测试了一下,做两次实验:
实验一
在开启事务的窗口里面执行查询操作,然后在另一个窗口插入数据,再次查询还是原来的数据,执行顺序如图:
实验二
在一个窗口A开启事务,在另一个窗口B插入数据,这次查询能查到这条数据,再次在窗口B插入数据,在窗口A不能查到数据了,事务的可重复读,执行顺序如图:
这说明开启了事务,会在一个 undo log
中创建这个数据的副本,InnoDB的一致性非锁定读,就是读取数据的副本,解释上面那句话就是,因为如果这个事务在 undo log 里面记录了一个被修改的行数据的副本,其他事务可能也用到了,就不能直接删除,需要确认这个数据没有被引用,才能删除,在purge线程中删除
我了解的差不多就这么多了,如果有错误,请留言批评指正!