文章目录
- 一:什么是redolog和binglog?
- 二:redolog和binlog可以相互替代或者只保留其一吗?
- 1. 可以使用binlog替代redolog进行数据恢复吗?
- 2. 可以只使用redolog而不使用binlog吗?
- 三:为什么redolog和binlog要进行二阶段提交?
- 四:二阶段提交步骤
- 五、redolog和binlog二阶段提交与redolog和binlog的顺序提交是否真的有区别?
- 六:恢复步骤?
一:什么是redolog和binglog?
redo log | Binglog | |
日志类型 | 物理日志 物理日志即数据页中的真实二级制数据,恢复速度快 | 逻辑日志 即sql语句,因需要逐条执行,恢复速度慢 |
存储格式 | innodb存储引擎数据的单位是页,redo log也是基于页进行存储,一个默认16K大小的页中存了很多512Byte的log block,log block的存储格式如下 [log block header 12Byte,log block body 492 Bytes,log block tailer 8 Bytes] | statement:SQL语句的形式 row:记录相关行的每一列的值(官方推荐) |
用途 | 重做数据页 | 数据复制 |
所处层级 | innodb存储引擎中 | 存储引擎的上层,因此不管用什么存储引擎,都可以开启binlog |
二:redolog和binlog可以相互替代或者只保留其一吗?
1. 可以使用binlog替代redolog进行数据恢复吗?
不可以
innodb利用wal技术进行数据恢复,write ahead logging技术依赖于物理日志进行数据恢复,binlog不是物理日志是逻辑日志,因此无法使用;
那么,为什么write ahead logging技术不可以使用逻辑日志进行数据恢复呢?这个问题可以考虑一下自增锁的场景,当自增锁的模式设置为innodb_autoinc_lock_mode = 2
时,mysql会锁住分配自增值的代码逻辑,不去进行自增值的预分配,由此带来的问题就是,高并发场景下多个事务中的insert(单条insert语句包含多个待插入值)逻辑会造成自增ID不固定的问题,由此带来的结果就是,利用binlog中的逻辑日志进行主从复制时,从库中的ID和主库中的ID不一致。因此,在特定场景下,逻辑日志相对于物理日志,显得不是那么可靠。
2. 可以只使用redolog而不使用binlog吗?
不可以
redolog是循环写,写到末尾要回到开头继续写,这样的日志无法保留历史记录,无法进行数据复制。
个人理解redolog其实是物理数据的一个缓存,理论上可以不需要redolog,插入的数据落盘后再返回插入成功,但是数据落盘的过程比较耗时,需要更新各种索引(B+树),因此现在数据落入redolog即返回成功,加快了返回速度。
三:为什么redolog和binlog要进行二阶段提交?
首先区分一个概念,commit①步骤是属于begin…commit②语句中的一个步骤,且是最后一个步骤,两个commit是包含的关系。
如果redo log持久化并进行了提交,而binlog未持久化数据库就crash了,则从库从binlog拉取数据会少于主库,造成不一致。因此需要内部事务来保证两种日志的一致性。
四:二阶段提交步骤
prepare:redolog写入log buffer,并fsync持久化到磁盘,在redolog事务中记录2PC的XID,在redolog事务打上prepare标识
commit:binlog写入log buffer,并fsync持久化到磁盘,在binlog事务中记录2PC的XID,同时在redolog事务打上commit标识
其中,prepare和commit阶段所提到的“事务”,都是指内部XA事务,即2PC
五、redolog和binlog二阶段提交与redolog和binlog的顺序提交是否真的有区别?
如果redolog和binlog顺序提交,则具体步骤会如下:
- redolog刷入cache并fsync刷盘,并打上commit标识
- binlog刷入cache并fsync刷盘
类比begin…commit和begin…rollback,commit和rollback这两个操作是只能二选一,且一旦commit则不能再rollback。同样,redolog中的事务一旦打上commit标识,是无法回退的,否则有可能覆盖其他事务的更新(例如A事务对某一行进行了插入并打上commit标识,而B事务紧接着对该行进行了修改,最后A事务突然回滚B事务,则B事务的操作被强制覆盖,这是不妥的)。如果redolog进行了commit,而此时数据库crash导致binlog刷盘失败,redolog无法回滚,会造成redolog和binlog不一致。
但是通过事务可以同时提交redolog和binlog,两者落盘之后都会记录2PC事务的XID(redolog和binlog中事务落盘的标识),若中途数据库crash,通过XID关联两者并在恢复时决定commit和rollback与否,详细步骤见下一段“恢复步骤”。
六:恢复步骤?
redolog中的事务如果经历了二阶段提交中的prepare阶段,则会打上prepare标识,如果经历commit阶段,则会打上commit标识(此时redolog和binlog均已落盘)。
Step1. 按顺序扫描redolog,如果redolog中的事务既有prepare标识,又有commit标识,就直接提交(复制redolog disk中的数据页到磁盘数据页)
Step2 .如果redolog事务只有prepare标识,没有commit标识,则说明当前事务在commit阶段crash了,binlog中当前事务是否完整未可知,此时拿着redolog中当前事务的XID(redolog和binlog中事务落盘的标识),去查看binlog中是否存在此XID
a. 如果binlog中有当前事务的XID,则提交事务(复制redolog disk中的数据页到磁盘数据页)
b. 如果binlog中没有当前事务的XID,则回滚事务(使用undolog来删除redolog中的对应事务)
可以将mysql redolog和binlog二阶段提交和广义上的二阶段提交进行对比,广义上的二阶段提交,若某个参与者超时未收到协调者的ack通知,则会进行回滚,回滚逻辑需要开发者在各个参与者中进行记录。mysql二阶段提交是通过xid进行恢复。
参考:
http://blog.itpub.net/28218939/viewspace-1975809/