通用:MySQL主库BinaryLog样例解析(ROW格式)

MySQL主库BinaryLog样例解析(ROW格式)

在生产环境中,BinaryLog以二进制形式存储,无法直接查看,需通过MySQL自带的mysqlbinlog工具解析为可读文本。以下基于前文配置的主库(binlog_format=ROW),提供真实的BinaryLog解析样例,涵盖"表结构变更(DDL)"和"数据行变更(DML)"两种核心场景,并标注关键字段含义。

一、前提:查看BinaryLog的实操命令

首先需掌握解析BinaryLog的核心命令,后续样例均通过以下方式生成:

1.1 查看主库当前BinaryLog列表

先确定要解析的BinaryLog文件名(如binlog.000001):

bash 复制代码
# 登录主库执行SQL,查看BinaryLog文件列表及大小
mysql -u root -p -e "SHOW BINARY LOGS;"

执行结果(示例):

Log_name File_size
binlog.000001 1562
binlog.000002 458

1.2 用mysqlbinlog解析BinaryLog

通过mysqlbinlog工具将二进制日志解析为可读文本,核心参数说明:

  • --base64-output=DECODE-ROWS:解析ROW格式的日志(必须加,否则显示乱码);
  • --verbose:显示详细的字段类型和值(便于理解数据变更);
  • --start-datetime/--stop-datetime:按时间范围过滤日志(可选,如只看2024-05-20的日志)。

解析命令示例 (解析binlog.000001中2024-05-20的日志):

bash 复制代码
mysqlbinlog \
--base64-output=DECODE-ROWS \
--verbose \
--start-datetime="2024-05-20 09:00:00" \
--stop-datetime="2024-05-20 18:00:00" \
/data/mysql/binlog/binlog.000001 > binlog_000001_parsed.sql

解析后会生成binlog_000001_parsed.sql文件,以下样例均来自该文件。

二、BinaryLog样例1:表结构变更(DDL - CREATE TABLE)

当主库执行CREATE TABLE创建表时,BinaryLog会记录完整的DDL语句(ROW格式下DDL仍以"语句"形式记录,因表结构变更无需行级细节)。

2.1 原始SQL操作(主库执行)

sql 复制代码
-- 主库创建test库下的products表(含主键、普通索引)
CREATE TABLE test.products (
    product_id INT PRIMARY KEY AUTO_INCREMENT,
    category_id INT NOT NULL,
    stock INT NOT NULL DEFAULT 0,
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_category (category_id)  -- 非唯一普通索引
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2.2 解析后的BinaryLog样例

sql 复制代码
# at 4
#240520  9:30:00 server id 100  end_log_pos 123 CRC32 0xabc12345 	Start: binlog v 4, server v 8.0.32-log created 240520  9:30:00
# Warning: this binlog is either in use or was not closed properly.
BINLOG '
abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ
'/*!*/;
# at 123
#240520  9:30:15 server id 100  end_log_pos 198 CRC32 0xdef67890 	Query	thread_id=10	exec_time=0	error_code=0
SET TIMESTAMP=1716202215/*!*/;
SET @@session.pseudo_thread_id=10/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1168113696/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8mb4 *//*!*/;
SET @@session.character_set_client=255, @@session.collation_connection=255, @@session.collation_server=255/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
CREATE TABLE test.products (
    product_id INT PRIMARY KEY AUTO_INCREMENT,
    category_id INT NOT NULL,
    stock INT NOT NULL DEFAULT 0,
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_category (category_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
/*!*/;
# at 198
#240520  9:30:15 server id 100  end_log_pos 230 CRC32 0x1a2b3c4d 	Rotate to binlog.000001  pos: 4

2.3 样例关键字段解读

字段/内容 含义
# at 123 该日志事件在BinaryLog中的起始偏移量(对应SHOW MASTER STATUS的Position)
#240520 9:30:15 日志事件的创建时间(格式:年-月-日 时:分:秒)
server id 100 生成该日志的服务器ID(即主库server-id=100,用于主从识别)
end_log_pos 198 该日志事件的结束偏移量(下一个事件从198开始)
Query 日志事件类型(DDL操作均为Query类型,DML在ROW格式下为Write_rows/Update_rows等)
thread_id=10 执行该操作的MySQL线程ID(可通过show processlist查看对应线程)
CREATE TABLE ... 完整的DDL语句(与主库执行的SQL完全一致,确保从库同步表结构)

三、BinaryLog样例2:数据行插入(DML - INSERT)

当主库执行INSERT插入数据时,ROW格式的BinaryLog会记录"插入行的完整字段值"(而非SQL语句),确保从库同步准确(即使含CURRENT_TIMESTAMP等函数)。

3.1 原始SQL操作(主库执行)

sql 复制代码
-- 主库插入2行数据到test.products表
INSERT INTO test.products (category_id, stock) 
VALUES (2, 100), (5, 200);

3.2 解析后的BinaryLog样例

sql 复制代码
# at 230
#240520  9:35:22 server id 100  end_log_pos 302 CRC32 0x5e6f7a8b 	Query	thread_id=11	exec_time=0	error_code=0
SET TIMESTAMP=1716202522/*!*/;
BEGIN
/*!*/;
# at 302
#240520  9:35:22 server id 100  end_log_pos 368 CRC32 0x9c8d7e6f 	Table_map: `test`.`products` mapped to number 108
# at 368
#240520  9:35:22 server id 100  end_log_pos 446 CRC32 0x3a4b5c6d 	Write_rows: table id 108 flags: STMT_END_F

BINLOG '
xyzabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRST
UVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQ
'/*!*/;
### INSERT INTO `test`.`products`
### SET
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2=2 /* INT meta=0 nullable=0 is_null=0 */
###   @3=100 /* INT meta=0 nullable=0 is_null=0 */
###   @4='2024-05-20 09:35:22' /* DATETIME meta=0 nullable=0 is_null=0 */
### INSERT INTO `test`.`products`
### SET
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */
###   @2=5 /* INT meta=0 nullable=0 is_null=0 */
###   @3=200 /* INT meta=0 nullable=0 is_null=0 */
###   @4='2024-05-20 09:35:22' /* DATETIME meta=0 nullable=0 is_null=0 */
# at 446
#240520  9:35:22 server id 100  end_log_pos 478 CRC32 0x7e8f9a0b 	Xid = 123
COMMIT/*!*/;

3.3 样例关键字段解读(ROW格式核心)

字段/内容 含义
BEGIN/COMMIT 事务的开始与提交(确保从库以事务方式执行,保证原子性)
Table_map 表映射事件:将test.products映射为内部表ID 108(后续事件通过ID关联表)
Write_rows 事件类型:表示"插入行"(对应INSERT操作;UPDATE为Update_rows,DELETE为Delete_rows)
### INSERT INTO ... 解析后的行数据(mysqlbinlog --verbose才会显示,默认二进制不显示)
@1=1 表的第1个字段(product_id)的值为1(@N对应表的第N个字段,按创建顺序)
@4='2024-05-20 09:35:22' 第4个字段(create_time)的值(自动填充的CURRENT_TIMESTAMP,从库直接使用该值,避免时间不一致)
Xid = 123 事务ID(用于主从事务一致性校验,确保从库不丢事务)

四、BinaryLog样例3:数据行更新(DML - UPDATE)

当主库执行UPDATE修改数据时,ROW格式的BinaryLog会记录"更新前的旧值"和"更新后的新值"(便于从库准确执行,且支持数据回滚场景)。

4.1 原始SQL操作(主库执行)

sql 复制代码
-- 主库更新category_id=2的行,将stock从100改为99
UPDATE test.products 
SET stock = 99 
WHERE category_id = 2;

4.2 解析后的BinaryLog样例

sql 复制代码
# at 478
#240520  9:40:30 server id 100  end_log_pos 550 CRC32 0x1c2d3e4f 	Query	thread_id=11	exec_time=0	error_code=0
SET TIMESTAMP=1716202830/*!*/;
BEGIN
/*!*/;
# at 550
#240520  9:40:30 server id 100  end_log_pos 616 CRC32 0x5a6b7c8d 	Table_map: `test`.`products` mapped to number 108
# at 616
#240520  9:40:30 server id 100  end_log_pos 688 CRC32 0x9e0f1a2b 	Update_rows: table id 108 flags: STMT_END_F

BINLOG '
abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWX
YZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTU
'/*!*/;
### UPDATE `test`.`products`
### WHERE
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2=2 /* INT meta=0 nullable=0 is_null=0 */
###   @3=100 /* INT meta=0 nullable=0 is_null=0 */
###   @4='2024-05-20 09:35:22' /* DATETIME meta=0 nullable=0 is_null=0 */
### SET
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2=2 /* INT meta=0 nullable=0 is_null=0 */
###   @3=99 /* INT meta=0 nullable=0 is_null=0 */
###   @4='2024-05-20 09:35:22' /* DATETIME meta=0 nullable=0 is_null=0 */
# at 688
#240520  9:40:30 server id 100  end_log_pos 720 CRC32 0x3c4d5e6f 	Xid = 124
COMMIT/*!*/;

4.3 样例关键字段解读(UPDATE核心)

字段/内容 含义
Update_rows 事件类型:表示"更新行"(区别于INSERT的Write_rows)
### WHERE 更新前的旧值(从库通过旧值定位要更新的行,避免因行顺序不一致导致错误)
### SET 更新后的新值(从库将定位到的行修改为新值,确保与主库一致)
@3=100(WHERE中) 旧的stock值为100(更新前)
@3=99(SET中) 新的stock值为99(更新后)

五、BinaryLog样例4:数据行删除(DML - DELETE)

当主库执行DELETE删除数据时,ROW格式的BinaryLog会记录"删除行的完整旧值"(从库通过旧值定位并删除对应行,确保删除准确)。

5.1 原始SQL操作(主库执行)

sql 复制代码
-- 主库删除product_id=2的行
DELETE FROM test.products 
WHERE product_id = 2;

5.2 解析后的BinaryLog样例

sql 复制代码
# at 720
#240520  9:45:15 server id 100  end_log_pos 792 CRC32 0x7f8a9b0c 	Query	thread_id=11	exec_time=0	error_code=0
SET TIMESTAMP=1716203115/*!*/;
BEGIN
/*!*/;
# at 792
#240520  9:45:15 server id 100  end_log_pos 858 CRC32 0x1d2e3f4a 	Table_map: `test`.`products` mapped to number 108
# at 858
#240520  9:45:15 server id 100  end_log_pos 914 CRC32 0x5b6c7d8e 	Delete_rows: table id 108 flags: STMT_END_F

BINLOG '
xyzabcdefghijklmnopqrst


---

> Studying will never be ending.

▲如有纰漏,烦请指正~~
相关推荐
W.Buffer7 小时前
通用:MySQL-InnoDB事务及ACID特性
数据库·mysql
qiushan_8 小时前
【Android】【Framework】进程的启动过程
android
用户2018792831678 小时前
Java经典一问:String s = new String("xxx");创建了几个String对象?
android
用户2018792831678 小时前
用 “建房子” 讲懂 Android 中 new 对象的全过程:从代码到 ART 的魔法
android
用户2018792831678 小时前
JVM类加载大冒险:小明的Java奇幻之旅
android
用户2018792831678 小时前
为何说Java传参只有值传递?
android
手机不死我是天子8 小时前
《Android 核心组件深度系列 · 第 4 篇 ContentProvider》
android·架构
鹏多多8 小时前
flutter-切换状态显示不同组件10种实现方案全解析
android·前端·ios
FengyunSky9 小时前
高通Camx内存问题排查
android·linux·后端