线上Java服务CPU突然飙到100%?别慌,用Arthas的thread命令5分钟定位到‘元凶’
2026/5/2 18:22:24
🌺The Begin🌺点点关注,收藏不迷路🌺 |
本文将深入探讨MySQL二进制日志的核心机制,涵盖其工作原理、配置方式、应用场景以及最佳实践,并辅以图表帮助理解。
二进制日志(Binary Log)是MySQL中最重要的日志之一,它记录了所有对数据库进行更改的SQL语句(DDL和DML),但不包括SELECT和SHOW这类查询操作。Binlog以二进制格式存储,主要用于数据复制、数据恢复和审计。
| 作用 | 说明 |
|---|---|
| 主从复制 | 主库将Binlog发送给从库,从库重放这些日志以实现数据同步 |
| 数据恢复 | 通过Binlog可以进行时间点恢复(PITR) |
| 审计 | 记录所有数据变更操作 |
-- 示例:一个简单的事务STARTTRANSACTION;UPDATEusersSETbalance=balance-100WHEREid=1;UPDATEusersSETbalance=balance+100WHEREid=2;COMMIT;为了保证数据一致性,MySQL使用了两阶段提交机制:
| 格式 | 描述 | 优点 | 缺点 | 示例 |
|---|---|---|---|---|
| STATEMENT | 记录SQL语句本身 | 日志量小,节省空间 | 可能存在主从不一致 | UPDATE users SET name='Alice' WHERE id=1; |
| ROW | 记录每行数据的变化 | 数据一致性好 | 日志量大 | 记录变更前后的整行数据 |
| MIXED | 混合模式 | 平衡空间和一致性 | 配置复杂 | 根据情况选择格式 |
-- 查看当前Binlog格式SHOWVARIABLESLIKE'binlog_format';-- 设置Binlog格式(需重启)-- 配置文件my.cnf中设置:-- [mysqld]-- binlog_format = ROW-- expire_logs_days = 7-- max_binlog_size = 100M-- 动态设置(会话级)SETSESSIONbinlog_format='ROW';-- 全局设置SETGLOBALbinlog_format='ROW';mysql-bin.index # Binlog索引文件 mysql-bin.000001 # Binlog文件1 mysql-bin.000002 # Binlog文件2 mysql-bin.000003 # Binlog文件3 ...+---------------------+ | Binlog Header | # 文件头,4字节魔数"0xfe 0x62 0x69 0x6e" +---------------------+ | Format Event | # 格式描述事件 +---------------------+ | Event 1 | # 第一个事件 +---------------------+ | Event 2 | # 第二个事件 +---------------------+ | ... | +---------------------+ | Event N | # 第N个事件 +---------------------+ | Rotate Event | # 轮转事件(文件末尾) +---------------------+每个事件包含以下部分:
+----------------------+ | 事件头(19字节) | +----------------------+ | Timestamp (4) | # 事件发生时间 | Type Code (1) | # 事件类型 | Server ID (4) | # 服务器ID | Event Size (4) | # 事件大小 | Next Pos (4) | # 下一个事件位置 | Flags (2) | # 标志位 +----------------------+ | 事件体(可变长度) | +----------------------+# my.cnf配置文件示例 [mysqld] # 启用Binlog log-bin = mysql-bin # Binlog格式 binlog_format = ROW # 过期时间(天) expire_logs_days = 7 # 单个文件大小 max_binlog_size = 100M # 缓存大小 binlog_cache_size = 32K # 同步策略 sync_binlog = 1 # 忽略的数据库 binlog-ignore-db = mysql # 仅记录的数据库 binlog-do-db = myapp| 值 | 含义 | 安全性 | 性能 |
|---|---|---|---|
| 0 | 由系统决定同步时机 | 最低 | 最高 |
| 1 | 每次提交都同步 | 最高 | 最低 |
| N | 每N次提交同步一次 | 中等 | 中等 |
-- 查看所有Binlog文件SHOWBINARYLOGS;-- 查看当前正在使用的Binlog文件SHOWMASTERSTATUS;-- 查看Binlog事件SHOWBINLOG EVENTSIN'mysql-bin.000001'FROM107LIMIT10;-- 清空所有BinlogRESET MASTER;-- 删除指定日期前的日志PURGEBINARYLOGS BEFORE'2024-01-01 00:00:00';-- 设置Binlog有效期SETGLOBALexpire_logs_days=10;# 查看Binlog内容mysqlbinlog mysql-bin.000001# 查看特定时间的日志mysqlbinlog --start-datetime="2024-01-01 00:00:00"\--stop-datetime="2024-01-02 00:00:00"\mysql-bin.000001# 将Binlog转换为SQL文件mysqlbinlog mysql-bin.000001>output.sql# 恢复指定数据库mysqlbinlog --database=myapp mysql-bin.000001|mysql -u root -p# 查看ROW格式的Binlog(解码)mysqlbinlog -v --base64-output=DECODE-ROWS mysql-bin.000001主库配置:
-- 设置server-idSETGLOBALserver_id=1;-- 创建复制用户CREATEUSER'repl'@'%'IDENTIFIEDBY'password';GRANTREPLICATIONSLAVEON*.*TO'repl'@'%';-- 查看主库状态SHOWMASTERSTATUS;-- 记下File和Position值从库配置:
CHANGE MASTERTOMASTER_HOST='master_host',MASTER_USER='repl',MASTER_PASSWORD='password',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=107;-- 启动复制STARTSLAVE;-- 查看复制状态SHOWSLAVESTATUS\G# 1. 恢复全量备份mysql -u root -p<full_backup.sql# 2. 恢复指定时间点前的Binlogmysqlbinlog --stop-datetime="2024-01-15 14:30:00"\mysql-bin.000001 mysql-bin.000002|mysql -u root -p# 3. 跳过错误事务(如果知道位置)mysqlbinlog --start-position=107--stop-position=500\mysql-bin.000001|mysql -u root -p-- 假设误删除了users表的数据-- 1. 查找删除操作的位置mysqlbinlog-v--base64-output=DECODE-ROWS \--start-datetime="2024-01-15 14:00:00" \mysql-bin.000001|grep-A10-B5"DELETE FROM users"-- 2. 找到位置后,恢复到删除前的状态mysqlbinlog--stop-position=107800 \mysql-bin.000001|mysql-u root-p-- 查看Binlog状态SHOWGLOBALSTATUSLIKE'Binlog%';-- 重要指标-- Binlog_cache_use: 使用Binlog缓存的次数-- Binlog_cache_disk_use: 临时文件写入次数(应尽量少)-- Binlog_stmt_cache_use: 语句缓存使用次数-- 查看Binlog文件大小SELECTLOG_NAME,FILE_SIZE/1024/1024asSIZE_MB,CREATE_TIMEFROMinformation_schema.BINARY_LOG_FILE_INFO;-- 1. 调整日志格式为STATEMENT-- 2. 减少过期时间SETGLOBALexpire_logs_days=3;-- 3. 定期清理PURGEBINARYLOGS BEFORE DATE_SUB(NOW(),INTERVAL3DAY);-- 1. 优化查询,减少大事务-- 2. 调整参数SETGLOBALsync_binlog=0;SETGLOBALinnodb_flush_log_at_trx_commit=2;-- 3. 使用并行复制SETGLOBALslave_parallel_workers=4;# 尝试修复mysqlbinlog --force mysql-bin.000001>recovered.sql# 检查文件完整性mysqlbinlog --verify mysql-bin.000001MySQL二进制日志是数据库高可用、数据安全的基石。合理配置和管理Binlog可以:
掌握Binlog的工作原理和操作技巧,是每个MySQL DBA的必备技能。在实际生产环境中,建议根据业务特点选择合适的Binlog格式,制定合理的清理策略,并建立完善的监控机制。
注意事项:
通过本文的详细讲解和实操示例,相信您已经对MySQL二进制日志有了全面深入的理解。在实际工作中,结合具体业务场景灵活运用这些知识,将能有效提升数据库的稳定性和可靠性。
🌺The End🌺点点关注,收藏不迷路🌺 |