# MySQL 复制 ## 一、日志格式 ### 1.1 二进制日志格式 MySQL 二进制日志是进行主从复制的基础,它记录了所有对 MySQL 数据库的修改事件,包括增删改查和表结构修改。当前 MySQL 一共支持三种二进制日志格式,可以通过 binlog-format 参数来进行控制,其可选值如下: + **STATEMENT**:段格式。是 MySQL 最早支持的二进制日志格式。其记录的是实际执行修改的 SQL 语句,因此在进行批量修改时其所需要记录的数据量比较小,但对于 UUID() 或者其他依赖上下文的执行语句,可能会在主备上产生不一样的结果。 + **ROW**:行格式,是 MySQL 5.7 版本之后默认的二进制日志格式。其记录的是修改前后的数据,因此在批量修改时其需要记录的数据量比较大,但其安全性比较高,不会导致主备出现不一致的情况。同时因为 ROW 格式是在从库上直接应用更改后的数据,其还能减少锁的使用。 + **MIXED**:是以上两种日志的混合方式,默认采用段格式进行记录,当段格式不适用时 (如 UUID() ),则默认采用 ROW 格式。 通常在主备之间网络情况良好的时,可以优先考虑使用 ROW 格式,此时数据一致性最高,其次是 MIXED 格式。在设置 ROW 格式时,还有一个非常重要的参数 binlog_row_image : ### 1.2 binlog_row_image binlog_row_image 有以下三个可选值: + **full**:默认值,记录行在修改前后所有列的值。 + **minimal**:只记录修改涉及列的值。 + **noblob**:与 full 类似,但如果 BLOB 或 TEXT 列没有修改,则不对其进行记录。 binlog-format 和 binlog_row_image 的默认值可能在不同版本存在差异,可以使用以下命令进行查看。通常情况下,为了减少在主备复制中需要传输的数据量,可以将 binlog_row_image 的值设置为 minimal 或 noblob。 ```sql show variables like 'binlog_format'; show variables like 'binlog_row_image'; ``` ## 二、基于二进制日志的复制 ### 2.1 复制原理 MySQL 的复制原理如下图所示: + 主库首先将变更写入到自己的二进制日志中; + 备库会启动一个 IO 线程,然后主动去主库节点上获取变更日志,并写入到自己的中继日志中。 + 之后从中继日志中读取变更事件,在从库上执行变更。 + 当备库与主库数据状态一致,备库的 IO 线程就会进入睡眠。当主库再次发生变更时,其会向备库发出信号,唤醒 IO 线程并再次进行工作。 如果没有进行任何配置,主库在将变更写入到二进制日志后,就会返回对客户端的响应,因此默认情况下的复制是完全异步进行的,主备之间可能会短暂存在数据不一致的情况。