什么是 Binlog
MySQL Server
有四种类型的日志——Error Log
、General Query Log
、Binary Log
和 Slow Query Log
。
第一个是错误日志,记录 mysqld
(mysql daemon
)的一些错误。第二个是一般查询日志,记录 mysqld
正在做的事情,比如客户端的连接和断开、来自客户端每条 Sql Statement
记录信息;如果你想知道客户端到底传了什么给服务端,这个日志就非常管用了,不过它非常影响性能。第四个是慢查询日志,记录一些查询比较慢的 SQL
语句——这种日志非常常用,主要是给开发者调优用的。
第三种就是 Binlog
了,binlog
是mysql的二进制日志,包含了一些事件,这些事件描述了数据库的改动,如建表、数据改动等,也包括一些潜在改动,比如 DELETE FROM ran WHERE bing = luan
,然而一条数据都没被删掉的这种情况。除非使用 Row-based logging
,否则会包含所有改动数据的 SQL Statement
。
注意:binlog
主要有statement-based
、row-based logging
和mixed logging
三种格式,row-based
的记录中不包括潜在更新记录。
Binlog
有两个重要的用途——复制和恢复。比如主从表的复制,和备份恢复。
注:mysqld
是MySQL
服务器的守护进程。
binlog格式
可以指定三种binary log的格式(启动时指定):
|
|
statement-based logging
: 基于SQL语句,Mysql5.6默认,某些语句和函数如UUID, LOAD DATA INFILE等在复制过程可能导致数据不一致甚至出错。row-based logging
:基于行,记录影响table中每一行的事务,很安全。所以一条语句可能会对应0-N个事件,记录很详细,数据同步的支持比STATEMENT
方式要好。但是binlog
会比其他两种模式大很多,在一些大表中清除大量数据时在binlog
中会生成很多条语句,可能导致从库延迟变大。mixed logging
:使用statement-based logging
作为默认,但是日志模式可能会在某些情况下自动切换到row-based logging
。
启用 Binlog
通常情况 MySQL
是默认关闭 Binlog
的,需要在my.cnf
中手动配置启用它。
|
|
启动MySQL
服务
|
|
启动MySQL
客户端
|
|
在客户端终端里面输入下面一句 SQL
语句:
|
|
显示结果如下:
|
|
结构解析
索引文件
索引文件就是 master-bin.index
文件,是一个普通的文本文件,以换行为间隔,一行一个文件名。比如它可能是:
|
|
然后对应的每行文件就是一个 Binlog
实体文件了。
Binlog 文件
Binlog
的文件结构大致由如下几个方面组成。
文件头
文件头由一个四字节 Magic Number
,其值为 1852400382
,在内存中就是 "\xfe\x62\x69\x6e"
.
与平常二进制一样,通常都有一个 Magic Number
进行文件识别,如果 Magic Number
不吻合上述的值那么这个文件就不是一个正常的 Binlog
。
事件
在文件头之后,跟随的是一个个事件依次排列。每个事件都由一个事件头和事件体组成。
事件头里面的内容包含了这个事件的类型(如新增、删除等)、事件执行时间以及是哪个服务器执行的事件等信息。
第一个事件是一个事件描述符,描述了这个 Binlog
文件格式的版本。接下去的一堆事件将会按照第一个事件描述符所描述的结构版本进行解读。最后一个事件是一个衔接事件,指定了下一个 Binlog
文件名——有点类似于链表里面的 next
指针。
事件头
一个事件头有 19 字节,依次排列为四字节的时间戳、一字节的当前事件类型、四字节的服务端 ID、四字节的当前事件长度描述、四字节的下个事件位置(方便跳转)以及两字节的标识。
Header
的格式如下:
|
|
事件体
事实上在 Binlog
事件中应该是有三个部分组成,header
、post-header
和 payload
,不过通常情况下我们把 post-header
和 payload
都归结为事件体,实际上这个 post-header
里面放的是一些定长的数据.
实际上一个真正的事件体由两部分组成:
|
|
而这个 post-header
对于不同类型的事件来说长度是不一样的,同种类型来说是一样的,而这个长度的预先规定将会在一个“格式描述事件”中定好。
标识更新操作
|
|
标识写入操作
|
|
col_num
: 代表字段的个数占用字节数是可变的,一般一字节就够了,1字节/2的八次方 一般也很难有表有几百个字段
map_col
: 这个代表字段是否为空,每一位映射一个列,描述是否被使用, N列的对应的size=int((N+7)/8)bytes
insert_value
:这个就是具体的记录内容。
标识binlog文件结束,以及新的binlog文件的名称和位置
|
|
格式描述事件
在 Magic Number
之后跟着的是一个格式描述事件,其实这只是在 v4 版本中的称呼,在以前的版本里面叫起始事件。
- v1,用于 MySQL 3.2.3
- v3,用于 MySQL 4.0.2 以及 4.1.0
- v4,用于 MySQL 5.0 以及更高版本
在 v4 版本中这个事件的结构如下:
|
|
这个事件的 type_code
是 15,然后 event_length
是大于等于 91 的值的,这个主要取决于所有事件类型数。
因为从第 76 字节开始后面的二进制就代表一个字节类型的数组了,一个字节代表一个事件类型的 post-header
长度,即每个事件类型固定数据的长度。
校验和
从5.6开始,如果服务器设置产生检验和的前提,事件末尾就多一个检验和字段,是一个32位整型数,用来检查时间写入后是否有损坏