mysql中binlog_format模式与配置详解

本文深入探讨MySQL的三种复制方式:基于SQL语句、基于行及混合模式复制,对比其优缺点,并解析binlog格式如何影响数据一致性。了解不同复制模式在性能与数据完整性间的权衡。

mysql复制主要有三种方式:
基于SQL语句的复制(statement-based replication, SBR),
基于行的复制(row-based replication, RBR),
混合模式复制(mixed-based replication, MBR)。
对应的,
binlog的格式也有三种:STATEMENT,ROW,MIXED。

① STATEMENT模式(SBR)
每一条会修改数据的sql语句会记录到binlog中。优点是并不需要记录每一条sql语句和每一行的数据变化,
减少了binlog日志量,节约IO,提高性能。缺点是在某些情况下会导致master-slave中的数据不一致(如
sleep()函数, last_insert_id(),以及user-defined functions(udf)等会出现问题)
② ROW模式(RBR)
不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了,修改成什么样了。而且不会出现某些特定情况下
的存储过程、或function、或trigger的调用和触发无法被正确复制的问题。缺点是会产生大量的日志,尤其是
alter table的时候会让日志暴涨。
③ MIXED模式(MBR)
以上两种模式的混合使用,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用
ROW模式保存binlog,MySQL会根据执行的SQL语句选择日志保存方式。

binlog复制配置
在mysql的配置文件my.cnf中,可以通过一下选项配置binglog相关
代码如下 复制代码

binlog_format = MIXED //binlog日志格式,mysql默认采用statement,建议使用mixed
log-bin = /data/mysql/mysql-bin.log //binlog日志文件
expire_logs_days = 7 //binlog过期清理时间
max_binlog_size = 100m //binlog每个日志文件大小
binlog_cache_size = 4m //binlog缓存大小
max_binlog_cache_size = 512m //最大binlog缓存大小
三 MIXED说明
对于执行的SQL语句中包含now()这样的时间函数,会在日志中产生对应的unix_timestamp()*1000的时间字符
串,slave在完成同步时,取用的是sqlEvent发生的时间来保证数据的准确性。
另外对于一些功能性函数slave能完成相应的数据同步,而对于上面指定的一些类似于UDF函数,
导致Slave无法知晓的情况,则会采用ROW格式存储
这些Binlog,以保证产生的Binlog可以供Slave完成数据同步。

现在来比较以下 SBR 和 RBR 2中模式各自的优缺点:
SBR 的优点:
历史悠久,技术成熟
binlog文件较小
binlog中包含了所有数据库更改信息,可以据此来审核数据库的安全等情况
binlog可以用于实时的还原,而不仅仅用于复制
主从版本可以不一样,从服务器版本可以比主服务器版本高

SBR 的缺点:
不是所有的UPDATE语句都能被复制,尤其是包含不确定操作的时候。
调用具有不确定因素的 UDF 时复制也可能出问题
使用以下函数的语句也无法被复制:

  • LOAD_FILE()
  • UUID()
  • USER()
  • FOUND_ROWS()
  • SYSDATE() (除非启动时启用了 --sysdate-is-now 选项)
    INSERT … SELECT 会产生比 RBR 更多的行级锁
    复制需要进行全表扫描(WHERE 语句中没有使用到索引)的 UPDATE 时,需要比 RBR 请求更多的行级锁
    对于有 AUTO_INCREMENT 字段的 InnoDB表而言,INSERT 语句会阻塞其他 INSERT 语句
    对于一些复杂的语句,在从服务器上的耗资源情况会更严重,而 RBR 模式下,只会对那个发生变化的记录产生影响
    存储函数(不是存储过程)在被调用的同时也会执行一次 NOW() 函数,这个可以说是坏事也可能是好事
    确定了的 UDF 也需要在从服务器上执行
    数据表必须几乎和主服务器保持一致才行,否则可能会导致复制出错
    执行复杂语句如果出错的话,会消耗更多资源

RBR 的优点:
任何情况都可以被复制,这对复制来说是最安全可靠的
和其他大多数数据库系统的复制技术一样
多数情况下,从服务器上的表如果有主键的话,复制就会快了很多
复制以下几种语句时的行锁更少:

  • INSERT … SELECT
  • 包含 AUTO_INCREMENT 字段的 INSERT
  • 没有附带条件或者并没有修改很多记录的 UPDATE 或 DELETE 语句
    执行 INSERT,UPDATE,DELETE 语句时锁更少
    从服务器上采用多线程来执行复制成为可能

RBR 的缺点:
binlog 大了很多
复杂的回滚时 binlog 中会包含大量的数据
主服务器上执行 UPDATE 语句时,所有发生变化的记录都会写到 binlog 中,而 SBR 只会写一次,这会导致频
繁发生 binlog 的并发写问题
UDF 产生的大 BLOB 值会导致复制变慢
无法从 binlog 中看到都复制了写什么语句
当在非事务表上执行一段堆积的SQL语句时,最好采用 SBR 模式,否则很容易导致主从服务器的数据不一致情况发生
另外,针对系统库 mysql 里面的表发生变化时的处理规则如下:
如果是采用 INSERT,UPDATE,DELETE 直接操作表的情况,则日志格式根据 binlog_format 的设定而记录
如果是采用 GRANT,REVOKE,SET PASSWORD 等管理语句来做的话,那么无论如何都采用 SBR 模式记录
注:采用 RBR 模式后,能解决很多原先出现的主键重复问题。

<think>我们正在讨论MySQL主从复制使用GTID时的配置问题,特别是关于binlog_format的设置。根据用户的问题,他想知道在使用GTID时是否必须设置binlog_format为ROW,以及完整的配置要求。 首先,回顾一下GTID复制的基本要求: - GTID模式(gtid_mode=ON) - 强制GTID一致性(enforce_gtid_consistency=ON) - 主库和从库的server_id必须唯一 关于binlog_format,根据MySQL官方文档,GTID复制并不强制要求binlog_format必须为ROW。实际上,GTID复制可以支持STATEMENT、ROW和MIXED三种格式。但是,官方推荐使用ROW格式,原因如下: 1. 数据一致性:ROW格式基于行复制,可以避免一些非确定性语句(如使用随机数或系统时间)导致的主从不一致问题。 2. 安全性:在MIXED模式下,当遇到非确定性语句时,MySQL会自动切换到ROW格式,但这可能导致复制中断或错误。而直接使用ROW格式可以避免这种切换带来的风险。 3. GTID的兼容性:虽然GTID支持STATEMENT和ROW,但STATEMENT模式在复制某些特殊语句时(如使用临时表)可能会出现问题。 然而,必须注意的是,在GTID复制中,如果使用STATEMENT或MIXED格式,需要确保所有事务都是确定性的,否则可能导致复制错误。因此,为了确保复制的稳定性和数据一致性,推荐使用ROW格式。 接下来,我们提供完整的GTID复制配置步骤,包括主库和从库的配置: ### 主库配置(Master) 1. 修改配置文件(如my.cnf): ```ini [mysqld] server_id=1 # 必须唯一 log_bin=mysql-bin # 启用二进制日志 gtid_mode=ON # 开启GTID模式 enforce_gtid_consistency=ON # 强制GTID一致性 binlog_format=ROW # 推荐设置为ROW,但不是强制要求 expire_logs_days=7 # 可选,设置日志过期时间 ``` 2. 重启MySQL服务使配置生效。 3. 创建复制用户: ```sql CREATE USER 'repl'@'%' IDENTIFIED BY 'your_password'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES; ``` ### 从库配置(Slave) 1. 修改配置文件(如my.cnf): ```ini [mysqld] server_id=2 # 必须唯一,且不同于主库 relay_log=mysql-relay-bin # 中继日志 read_only=ON # 建议设置为只读 gtid_mode=ON enforce_gtid_consistency=ON binlog_format=ROW # 推荐主库一致 ``` 2. 重启MySQL服务。 ### 初始化数据同步 1. 在主库使用mysqldump备份数据(注意使用--master-data选项): ```bash mysqldump -u root -p --all-databases --master-data --single-transaction --gtid-purged=AUTO > full_backup.sql ``` - `--master-data`:会记录备份时对应的binlog位置,但在GTID模式下,我们主要使用GTID。 - `--gtid-purged=AUTO`:自动处理GTID信息,确保从库不会重复执行已包含在备份中的事务。 2. 将备份文件复制到从库并导入: ```bash mysql -u root -p < full_backup.sql ``` ### 启动复制 在从库执行: ```sql CHANGE MASTER TO MASTER_HOST='master_ip', MASTER_USER='repl', MASTER_PASSWORD='your_password', MASTER_AUTO_POSITION=1; # 启用GTID自动定位 START SLAVE; ``` ### 验证复制状态 ```sql SHOW SLAVE STATUS\G ``` 检查: - Slave_IO_Running: Yes - Slave_SQL_Running: Yes - Retrieved_Gtid_Set: 显示从主库接收的GTID集合 - Executed_Gtid_Set: 显示从库已执行的GTID集合 ### 结论 - **GTID复制不强制要求binlog_format=ROW**,但强烈推荐使用ROW格式以确保数据一致性和复制稳定性。 - 如果使用STATEMENT或MIXED格式,需要确保所有事务都是确定性的,否则可能导致复制错误。 ### 注意事项 -配置GTID复制前,确保所有服务器版本支持GTID(MySQL 5.6及以上版本)。 - 如果从传统复制切换到GTID复制,需要按照特定步骤进行,避免数据不一致。 §§相关问题§§ 1. 为什么在GTID复制中推荐使用ROW格式的二进制日志? 2. 如何将现有的非GTID主从复制迁移到GTID模式? 3. 在GTID复制中,如何跳过特定的错误事务? 4. GTID复制相对于传统复制有哪些优势?</think>### MySQL GTID复制中`binlog_format`配置详解 #### 核心结论 **GTID复制不强制要求`binlog_format=ROW`**,但**强烈推荐使用ROW格式**。以下是完整配置说明: --- ### 一、GTID`binlog_format`关系 | 复制模式 | 支持GTID | 推荐等级 | 风险说明 | |----------------|----------|----------|----------| | **ROW** | ✅ 完全支持 | ★★★★★ | 最安全,数据一致性最高[^3] | | **MIXED** | ✅ 支持 | ★★★☆☆ | 非确定性语句自动转ROW,有切换风险 | | **STATEMENT** | ⚠️ 有限支持 | ★☆☆☆☆ | 易导致主从不一致,不推荐[^1] > **关键说明**: > 1. GTID本身不依赖binlog格式,但**STATEMENT模式在复制非确定性语句(如`RAND()`/`NOW()`)时会导致数据不一致** > 2. 官方文档明确建议:*"For best results with GTID transactions, use `binlog_format=ROW`"* --- ### 二、完整GTID复制配置要求 #### 主库配置 (`my.cnf`) ```ini [mysqld] server_id = 1 # 全局唯一ID log_bin = /var/log/mysql/mysql-bin.log gtid_mode = ON # 核心GTID开关 enforce_gtid_consistency = ON # 强制GTID安全约束 binlog_format = ROW # ★ 强烈推荐设置 ★ expire_logs_days = 7 # 日志保留周期 ``` #### 从库配置 (`my.cnf`) ```ini [mysqld] server_id = 2 # 区别于主库 relay_log = /var/log/mysql/mysql-relay-bin read_only = ON # 从库写保护 gtid_mode = ON enforce_gtid_consistency = ON binlog_format = ROW # 主库一致 log_slave_updates = ON # 级联复制必需 ``` #### 必须重启的操作 ```bash # 主从库均需执行 systemctl restart mysqld ``` #### 初始化命令示例 ```sql -- 主库创建复制用户 CREATE USER 'repl'@'%' IDENTIFIED BY 'SecurePass123!'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; -- 从库启动GTID复制 CHANGE MASTER TO MASTER_HOST = '192.168.1.100', MASTER_USER = 'repl', MASTER_PASSWORD = 'SecurePass123!', MASTER_AUTO_POSITION = 1; -- ★ GTID核心参数 ★ START SLAVE; ``` --- ### 三、为什么推荐ROW模式? 1. **数据一致性保障** ROW格式直接记录行变更,避免STATEMENT模式下函数/触发器导致的主从差异[^3] 2. **冲突解决优势** 当复制出错时,ROW格式的二进制日志可直接用于数据修复: ```sql SHOW BINLOG EVENTS IN 'mysql-bin.000002' FROM 12345; ``` 3. **GTID特性兼容** ROW格式完美支持`MASTER_AUTO_POSITION=1`的自动故障转移 4. **空间效率优化** 虽然ROW日志较大,但配合`binlog_row_image=MINIMAL`可减少30-50%日志量: ```ini binlog_row_image = MINIMAL # 只记录变更列 ``` --- ### 四、特殊场景处理 #### 若必须使用STATEMENT模式 1. 需严格限制: ```sql SET GLOBAL enforce_gtid_consistency=ON; ``` 2. 禁止使用: - `CREATE TABLE ... SELECT` - 非确定性函数(`UUID()`, `RAND()`等) - 临时表操作 #### MIXED模式注意事项 当检测到非确定性语句时自动切换ROW格式,但可能造成: - 日志量突增 - 复制延迟波动 - 格式切换失败风险(需监控`SHOW SLAVE STATUS`) --- ### 五、验证配置 ```sql -- 检查GTID状态 SHOW GLOBAL VARIABLES LIKE 'gtid_mode'; /* 正确输出: gtid_mode | ON */ -- 验证复制格式 SELECT @@global.binlog_format; /* 推荐输出: ROW */ -- 监控复制错误 SHOW SLAVE STATUS\G /* 关键指标: Slave_IO_Running: Yes Slave_SQL_Running: Yes Last_IO_Error: Last_SQL_Error: */ ``` > 通过以上配置,GTID复制可自动管理事务位置,无需手动跟踪`binlog_file`和`binlog_pos`[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值