深入理解MySQL系列之redo log、undo log和binlog (3)

原来的记录被标记删除,删除版本号为2,并插入新记录,创建版本号为2

id name create version delete version
1   test   1   2  
1   new test   2    

删除操作:把事务版本作为删除版本号

如事务3把记录删除
delete from table where id = 1;

id name create version delete version
1   test   2   3  

查询操作

需满足以下两个条件的记录才能被事务查询出来:

InnoDB只查找版本早于当前事务版本的数据行

行的删除版本要么未定义,要么大于当前版本号,这可以确保事务读取到的行,在事务未开始之前未被删除

MVCC好处:减少锁的争用,提升性能

binlog 二进制文件概念及作用

二进制文件(binary log)记录了对MySQL数据库执行更改的所有操作(不包含SELECT、SHOW等,因为对数据没有修改)

二进制文件主要几种作用:

恢复:某些数据的恢复需要二进制日志

复制: 通过复制和执行二进制日志使一台远程的MySQL(slave)与另一台MySQL数据库(master)进行实时同步

审计: 用户可以通过二进制日志中信息来进行审计,判断是否有对数据库进行注入的攻击

二进制文件三个格式

MySQL 5.1开始引入binlog_format参数,该参数可设值有STATEMENT、ROW和MIX

STATEMENT: 二进制文件记录的是日志的逻辑SQL语句

ROW:记录表的行更改情况。如果设置了ROW模式,可以将InnoDB事务隔离级别设为READ_COMMITTED,以获得更好的并发性

MIX:MySQL默认采用STATEMENT格式进行二进制文件的记录,但在一些情况下会使用ROW,可能的情况有:

表的存储引擎为NDB,这时对表DML操作都以ROW格式进行

使用了UUID()、USER()、CURRENT_USER()、FOUND_ROWS()、ROW_COUNT()等不确定函数

使用了INSERT DELAY语句

使用了用户定义函数

使用了临时表

redo log和二进制文件区别

(二进制文件用来进行POINT-IN-TIME(PIT))的恢复及主从复制环境的建立。

二进制文件会记录所有与MySQL数据库有关的日志记录,包括InnoDB、MyISAM等其他存储引擎的日志。而InnoDB存储引擎的重做日志只记录有关该存储引擎本身的事务日志。

记录的内容不同,无论用户将二进制日志文件记录的格式设为STATEMENT、ROW或MIXED,其记录的都是关于一个事务的具体操作内容,即该日志是逻辑日志。而InnoDB存储引擎的重做日志文件记录的是关于每个页的更改的物理情况。

此外,写入的时间页不同,二进制日志文件仅再事务提交前进行提交,即只写磁盘一次,不论这时该事务多大。而在事务进行的过程中,却不断有重做日志条目(reod entry)被写入到重做日志文件中。

深入理解MySQL系列之redo log、undo log和binlog

group commit

若事务为非只读事务,则每次事务提交时需要进行一次fsync操作,以此保证重做日志都已经写入磁盘。但磁盘fsync性能有限,为提高磁盘fsync效率,当前数据库都提供group commit功能,即一次可以刷新确保多个事务日志被写入文件。

对InnoDB group commit,进行两阶段操作:

修改内存中事务对应的信息,并且将日志写入重做日志缓冲

调用fsync将确保日志都从重做日志缓冲写入磁盘

InnoDB1.2前,开启二进制文件,group commit功能失效问题:

开启二进制文件后,其步骤如下:
1)当事务提交时,InnoDB存储引擎进行prepare操作
2)MySQL数据库上层写入二进制文件
3)InnoDB将日志写入重做日志文件

a)修改内存中事务对应的信息,并将日志写入重做日志缓冲

b)调用fsync将确保日志都从重做日志缓冲写入磁盘

其中在保证MySQL数据库上层二进制文件的写入顺序,和InnoDB事务提交顺序一致,MySQL内部使用了prepare_commit_mutex锁,从而步骤3)中a)步不可以在其他事务执行步骤b)时进行,从而导致roup commit功能失效。

在这里插入图片描述

解决方案便是BLGC(Binary Log Group Commit)

MySQL 5.6 BLGC实现方式分为三个阶段:

Flush阶段:将每个事务的二进制文件写入内存

Sync阶段:将内存中的二进制刷新到磁盘,若队列有多个事务,那么仅一次fsync操作就完成了二进制日志的写入,这就是BLGC

Commit阶段:leader根据顺序调用存储引擎层事务提交,由于innodb本就支持group commit,所以解决了因为锁 prepare_commit_mutex 而导致的group commit失效问题。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpzzzp.html