- [bin log](#bin-log) - [Introduce](#introduce) - [binary log构成](#binary-log构成) - [binary log用途](#binary-log用途) - [binary log variable](#binary-log-variable) - [binlog\_encryption](#binlog_encryption) - [log\_bin](#log_bin) - [binlog\_checksum](#binlog_checksum) - [binary log format](#binary-log-format) - [mysqlbinlog](#mysqlbinlog) - [sync\_binlog](#sync_binlog) - [Binary Logging Format](#binary-logging-format) - [STATEMENT](#statement) - [ROW](#row) - [MIXED](#mixed) - [mysql表更新操作的binary log记录格式](#mysql表更新操作的binary-log记录格式) # bin log ## Introduce ### binary log构成 binary log由一系列描述数据库变动的事件构成,例如table creation操作或对table data进行的修改操作。 除上述对数据库造成修改的事件外,binary log中还包含`可能会潜在对数据库造成修改的statement`所对应的事件(例如一个没有匹配任何行的delete语句)。 binary log中还会包含每条statement更新数据所花费的时间。 ### binary log用途 binary log用途主要用于如下方面: - `for replication`:source replication server中的binary log提供了要发送给replicas的数据变动。source replication server会将binary log中包含的消息发送给replcias,replicas则是会重新执行这些变动。 - `for data recovery`:某些data recovery操作需要使用binary log。当backup被恢复后,需要对binary log中位于backup之后的时间进行重新执行操作 binary log不会记录`SELECT`或`SHOW`这些并不会对数据库数据进行修改的动作。如果想要对所有statement做记录,需要使用general query log。 在运行mysql server时开启binary log通常会令性能有所降低,但是能带来主从复制和数据恢复方面的好处。 binary log能兼容程序的意外中止,只有已完成的event或transaction才能记录到binary log或从binary log中read back。 写入binary log中的statement如果包含密码,密码将会被server重写,binary log中不会出现密码的明文。 ### binary log variable #### binlog_encryption binary log和relay log可以被加密,用于保护这些日志文件的数据安全。可以通过`binlog_encryption`变量来设置binary log是否被加密。 #### log_bin 通过`log_bin`可以设置binary log是否被启用,`log_bin`环境变量默认为`ON`,是启用的。 如果要在启动mysqld时禁用binary log,可以在`my.cnf`中指定`skip-log-bin`或`disable-log-bin`。 可以通过`--log-bin[=base_name]`来指定binary log file的base name。如果没有指定`--log-bin`选项,那么base name默认为`binlog`(binary log文件名为`binlog.xxxxx`。 mysqld会在base name之后追加数字将其作为binlog的文件名称,每次创建新的binlog文件时,数字都会递增。mysqld会在如下场景下创建新的binlog文件: - mysql server执行`start`或`restart`操作 - server对log进行`flush`操作 - 当前log大小达到`max_binlog_size`的大小 如果在事务中写入大量数据,那么binlog的大小可能会大于`max_binlog_size`,因为同一个事务中的event只会被记录到一个binlog中,不会写入到多个binlog中。 > #### binary log index > 为了追踪当前mysql使用了哪些binary log文件,mysqld创建了一个`binary log index`文件,其中包含了`binary log`文件的文件名。可以通过`--log-bin-index[=filename]`来指定`log index file`的名称。 #### binlog_checksum 默认情况下,server在输出event到日志时,会同时输出event的长度,并且用event长度来校验是否输出正确。除此之外,可以通过设置`binlog_checksum`来让server在输出event的同时输出event的checksum。在从binlog中read back时,source默认会使用event length,但是可以通过设置`source_verify_checksum`为启用来使用checksum。作为接收方的replica会校验从source接收到的event。 ### binary log format binary log中event目前支持三种格式: - row-based-logging - statement-based-logging - mixed-based-logging ### mysqlbinlog 当想要展示binary log文件中的内容时,可以使用mysqlbinlog工具,如果想要重新执行binlog中对应的statement,该工具将十分有用。 ```bash mysqlbinlog /var/lib/mysql/binlog.000503 | less ``` 通过上述命令可以查看binlog的内容。 可以通过如下命令来根据binlog内容更新数据库信息: ```bash mysqlbinlog log_file | mysql -h server_name ``` binary logging操作会在statement或transaction执行完成后立马被执行,但是logging操作在`锁释放`和`commit提交`之前。这将会保证日志将会按照commit的顺序来打印。 对非事务(引擎不支持事务)的表进行操作,在执行后会立即将log打印到binary log file中。 对于事务的表(例如innodb)表,在一个尚未提交的事务中,所有更新操作(update/insert/delete)将会被缓存,直到执行commit操作。在执行commit前,会将缓存中的整个事务都写入到binary log中。 ### sync_binlog 默认情况下,在每次写操作后,binary log都会被同步到磁盘中(sync_binlog为1)。如果`sync_binlog`没有被启用,并且系统发生宕机,那么位于binary log末尾的statements可能会丢失。为了保证不发生binlog文件丢失的情况,`sync_binlog`会设置每经过`N`次commit group之后,将binary log同步到disk中。 在早期的mysql版本中,即使将`sync_binlog`设置为1,也有可能发生table content和binlog content不一致的情况。在使用innodb tables并且mysql server处理了commit statement,那么其会将所有prepared transactions按顺序写入到binary log,并将binary log同步到disk中,并且提交innodb事务。 但是,在`同步binary log到disk`和`提交innodb事务`之间,server有可能会宕机,在server重启之后transaction会被回滚,但是事务对应event已经被写入到了binary log中,此时会发生binary log和table content不一致的情况。 上述情况在之前的mysql发行版中已经被解决,只需启用XA两阶段事务即可。在mysql 8.4中,innodb针对两阶段提交的XA事务支持一直是被启用的。 Innodb在XA事务中对两阶段提交的支持确保了binary log和innodb data files的一致性。在innodb隐式支持了XA两阶段事务之后,如果sync_binlog被设置,那么当server崩溃后重启时,会对未提交事务做回滚,同时会扫描binlog中最后的部分来收集`xid`,从而计算出binary log file中的`最后有效位置`。mysql server会告知innodb完成所有写入到binary log中的prepared transactions,并且将binary log file截取到最后有效位置。这将会保证table content和binary log的一致性。 ## Binary Logging Format 在binary log中,会采用如下集中格式来记录消息: ### STATEMENT mysql中的复制功能最初是基于sql statement的传播,sql statement将会从source实例发送到replica实例。这种行为被称作`statement-based logging`。 在启动server时,可以通过指定`--binlog-format=STATEMENT`来使用`statement-based logging`。 ### ROW 默认情况下,使用的是`row-based logging`。source实例会在`行数据如何被修改`的维度,向binary log中写入事件。 在启动server时,可以通过指定`--binlog-format=ROW`来使用`row-based logging`。 ### MIXED 在使用mixed-based logging时,`statement-based logging`会被默认使用,但是遇到下列描述的场景时,会自动切换到`row-based-logging`。 在启动server时,可以通过指定`--binlog-format=MIXED`来使用`mixed-based logging`。 随着使用的存储引擎不同,logging format也会收到影响和限制。 ### mysql表更新操作的binary log记录格式 对数据库中表数据的更改可以通过直接或间接的方式完成: - 直接: `INSERT, UPDATE, DELETE, REPLACE, DO, LOAD DATA, SELECT, and TRUNCATE TABLE` - 间接:`GRANT, REVOKE, SET PASSWORD, RENAME USER` 对于直接修改mysql表内容的语句,`log format`将会基于`binlog_format`配置。 对于间接修改表内容的语句,将会忽略`binlog_format`配置,直接以`STATEMENT`的形式写入到binary log中。