@Catyee
2021-01-06T16:35:20.000000Z
字数 3764
阅读 497
mysql
mysql binlog即mysql二进制日志或者归档日志,属于逻辑日志,记录了会引起数据库状态变化的操作信息,比如用户执行的DDL和DML语句,但是不包含select、show等查询语句,binlog中以事件(event)的形式保存这些操作的信息,还包含了事件的时间、开始以及结束位置。
在mysql的三层结构中,binlog属于server层的日志,也就是说binlog与存储引擎无关,不管是事务引擎innodb还是非事务引擎myisam都会产生binlog。对于事务表来说,一个事务可能包含多个事件,但是只有在提交事务的时候(commit前)才会一次性将这些事件写入文件(但可能还未刷盘,刷盘与sync_binlog参数有关),而对于非事务表来说每次执行完语句都会直接写入。
binlog主要用于数据复制和恢复,属于mysql的CDC方案(change data capture)。
binlog日志包括两类文件:
binlog索引文件和binlog文件的命名方式可以通过参数进行设置,自行查询。
binlog文件的结构:
每个binlog文件以一个4字节的魔数开头,接着是一组Event,每个Event包含header和data两个部分,header记录了Event的创建时间,位置、服务器等信息,data部分记录的是该Event的具体内容,如具体数据的修改;
binlog文件中的第一个Event用于描述binlog文件的格式版本,这个格式就是event写入binlog文件的格式,第一个event的类型固定为format_description_event(mysql5.0之后版本),其余的Event按照第一个Event的格式版本写入,最后一个Event用于说明下一个binlog文件。如图所示:
binlog中所有event类型可以参考官方文档:https://dev.mysql.com/doc/internals/en/event-classes-and-types.html
binlog中事件记录的格式:
binlog中事件记录的格式取决于用户配置的记录格式。mysql支持三种格式类型,可以通过binlog-format参数进行指定:
与binlog相关的参数有很多,但是个人认为最重要的只有以下4个:
事务日志指innodb的redo log和undo log,binlog是mysql server层面的日志,与存储引擎无关,任何存储引擎的表都会产生binlog;而事务日志是innodb存储引擎特有的;
innodb中redo log是物理日志,记录的是对数据页的操作;undo log是逻辑日志,记录的是回滚所需要的操作,比如一条insert,undo log对应到delete,undo log也会产生redo log。binlog是逻辑日志,记录的是用户对表的逻辑操作。
事务日志主要用来实现数据库的崩溃恢复,以及实现事务的ACD属性(隔离性用锁来实现),而binlog主要用于数据复制或者逻辑恢复。
当我们执行一个事务的时候,对于redo log和undo log,不会等到commit的时候一次性写入,而是边执行边写入的;对于binlog则是在commit前一次性写入的,写入之前都在缓存当中。
这是两个完全不同的过程,试想一下如果先写redo log后写binlog,假设在redo log写完binlog还没有写完的时候,MySQL进程异常重启,由于redo log已经写完,所以仍然能够把数据恢复回来,但是binlog没有记录这条语句,binlog中就缺失了一个事务;如果先写binlog后写redo log,在binlog写完而redo log没写完就crash,崩溃恢复以后这个事务被回滚,binlog中就多记录了一个事务,用binlog进行同步就会出现问题;
为了使redo log和binlog保持一致,mysql使用了两阶段提交的方式。事务总是begin...commit的过程,在最后提交事务的commit命令发出去的时候,redo log也需要记录commit命令的日志,但是这commit事件的日志记录被拆成了两个阶段:prepare和commit(此commit指两阶段提交的commit,上面的commit指事务的commit),也就是说redo log先记录2PC的XID,并打上prepare的标志,然后等待binlog写入,binlog在记录事务的时候也会记录XID,binlog写完之后redo log进入2PC的commit阶段,也就将prepare标志改为commit标志,一旦改完意味着事务已经提交,这个时候binlog和redo log都已经写入。如果在prepare阶段mysql宕机,重启恢复的时候先通过XID判断对应的binlog是否存在,如果存在,则可以继续提交事,如果不存在则需要回滚。如果恢复的时候发现redo log都没有进入prepare阶段则直接回滚。
使用mysqlbinlog工具可以查看binlog的具体内容,也可以进行mysql的逻辑备份与还原(还原只能到库级别,不能到表级别)
详细的使用方式见官网:https://dev.mysql.com/doc/refman/8.0/en/mysqlbinlog.html