查看binlog和GTID的当前状态,验证一条事务后GTID计数器精确加1,再用SHOW BINLOG EVENTS看ROW格式binlog记录的事件结构。
binlog是MySQL记录"发生了什么改动"的日志,GTID是给每个事务分配的全局唯一编号。
结果SHOW VARIABLES LIKE 'log_bin' → ON SHOW VARIABLES LIKE 'gtid_mode' → ON SHOW VARIABLES LIKE 'binlog_format' → ROW SHOW BINARY LOG STATUS → File: binlog.000002 → Position: 73487330 → Executed_Gtid_Set: efd7431a-b8ac-11f1-be90-82c03ef30a57:1-143
一个小发现:老版本教程里常见的 SHOW MASTER STATUS,在这个版本已经改名成了 SHOW BINARY LOG STATUS(语法报错验证过,旧写法在这个版本压根不认)。
GTID的格式是"server-uuid:序号范围",每个事务都会拿到一个新序号。
结果执行前: efd7431a-b8ac-11f1-be90-82c03ef30a57:1-143 INSERT INTO t10 (email) VALUES ('gtid-test@x.com'); 执行后: efd7431a-b8ac-11f1-be90-82c03ef30a57:1-144
一条的INSERT语句,GTID区间从1-143精确变成了1-144——每一个提交的事务,不管改了多少行,都会拿到唯一的一个GTID编号,这个编号全局唯一(前缀是这台server的UUID),在主从复制场景里,靠比较GTID集合就能精确判断某个事务有没有被执行过,不需要靠binlog文件名+偏移量这种脆弱的定位方式。
binlog_format=ROW意味着记录的是每一行数据的变化,不是SQL语句本身。
结果(SHOW BINLOG EVENTS片段)Table_map table_id: 86 (demo.t1) Write_rows table_id: 86 flags: USE_SQL_FOREIGN_KEY_F Write_rows table_id: 86 flags: USE_SQL_FOREIGN_KEY_F Write_rows table_id: 86 flags: USE_SQL_FOREIGN_KEY_F ...(连续多条Write_rows事件)
Table_map 事件(说明接下来的数据行属于哪张表),后面跟着一串 Write_rows 事件,每条携带一批实际写入的行数据(受 binlog_row_event_max_size 限制,太大的一批会被拆成多个事件)。这就是ROW格式binlog的样子:记录的是数据本身的变化,而不是产生这个变化的SQL语句——这也是为什么ROW格式复制比老式的STATEMENT格式更可靠:不管原始SQL里有没有用到不确定函数(如NOW()、RAND()),复制到从库时执行的都是完全一致的具体数据行,不会出现主从结果不一致的问题。
每一步都是本文上面用MySQL跑出来的原始结果。
SHOW BINARY LOG STATUS / SHOW BINLOG EVENTS:查看binlog与GTID状态