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.
▲如有纰漏,烦请指正~~