MySQL事务ID(DB_TRX_ID)和回滚指针(DB_ROLL_PTR)作为隐藏列存储在聚簇索引记录的行数据体中,位于用户字段之后、可变长度偏移数组之前,而非record header里;隐式主键my_row_id仅在无显式主键且启用sql_generate_invisible_primary_key时添加,为8字节真实列。

记录头信息(record header)只管“怎么管理这行”,不管“这行是谁改的”
record header 是固定 5 字节(某些版本为 4.5 字节)的元数据区域,用于页内链表组织和状态标记,比如:
- deleted_flag:该行是否被逻辑删除
- min_rec_mask:是否是页内最小记录(B+ 树导航用)
- n_owned:本记录拥有的记录数(用于页内槽位管理)
- heap_no:堆中编号(标识页内位置)
- next_record:指向页内下一条记录的偏移量(形成单向链表)
它不包含 trx_id、roll_pointer,更不包含 row_id 或 my_row_id。这些字段属于“行数据本身”,不是头信息。
事务 ID(DB_TRX_ID)和回滚指针(DB_ROLL_PTR)是强制存在的隐藏列
只要使用 InnoDB,每条聚簇索引记录都必须携带:
- DB_TRX_ID:6 字节,最后一次修改该行的事务 ID,用于 MVCC 可见性判断
- DB_ROLL_PTR:7 字节,指向 undo log 中前一版本记录的指针,用于回滚和一致性读
它们紧贴在用户字段之后写入,顺序固定,且对 SQL 不可见。即使你建表时指定了主键,这两个字段也始终存在——没有例外。
隐式主键(my_row_id)只在特定条件下出现,且是“真实列”,不是头信息
当开启 sql_generate_invisible_primary_key=ON 且建表未声明主键时,InnoDB 会自动添加一个名为 my_row_id 的列:
- 类型为
unsigned bigint NOT NULL AUTO_INCREMENT - 被设为聚簇索引键(即真正主键)
- 占用 8 字节(不是 6 字节),并参与排序和 B+ 树构建
- 它和 DB_TRX_ID、DB_ROLL_PTR 是并列的隐藏字段,但地位不同:前者是用户表结构的一部分(只是不可见),后两者是引擎级运行时必需元数据
注意:这个 my_row_id 和老式“无主键时自动生成的 6 字节 DB_ROW_ID”是两套机制——后者已被新隐式主键功能逐步替代,且不再用于聚簇索引构造。
为什么有人误以为它们在 record header 里?
因为官方文档常把“行格式组成”笼统说成“用户字段 + 隐藏字段 + 头信息”,而实际物理布局是:
[record header][user columns][hidden columns: my_row_id?][DB_TRX_ID][DB_ROLL_PTR][null bitmap][variable-length offset array]DB_TRX_ID 和 DB_ROLL_PTR 确实靠近开头,但它们属于数据体末段的固定长度尾部字段,不是 header。header 始终在最前面,且长度固定、功能纯粹。


















