MySQL InnoDB 记录(行)的完整字段详解

在 InnoDB 存储引擎中,一条记录的完整结构不仅包含用户定义的列,还包含多个 系统隐藏字段。这些隐藏字段是 InnoDB 实现事务(ACID)、多版本并发控制(MVCC)和索引机制的核心。以下是逐条解析:

1. 用户定义的列(User Columns)

即表结构中用户明确定义的字段,例如

CREATE TABLE users (
    id INT PRIMARY KEY,          -- 主键列
    name VARCHAR(50),            -- 普通列
    age INT,                     -- 普通列
    created_at TIMESTAMP         -- 普通列
);
  • 存储内容:用户插入或更新的具体数据。
  • 物理存储:根据行格式(如 COMPACT、DYNAMIC)压缩存储。

2. 系统隐藏字段(System Columns)

InnoDB 自动为每条记录添加以下隐藏字段:

2.1 DB_ROW_ID(行ID)

  • 作用:
    当表未定义主键时,InnoDB 自动生成一个 6 字节的隐式主键(DB_ROW_ID)。
    若表有自定义主键,则此字段不生成。
  • 特点:
    全局单调递增,用于唯一标识记录。
    用户无法直接访问,但可通过特殊工具(如 InnoDB 表空间解析工具)查看。

2.2 DB_TRX_ID(事务ID)

  • 作用:
    记录最后一次修改该行数据的事务ID(即 trx_id)。
    用于 MVCC,判断数据版本对当前事务的可见性。
    大小:6 字节。
  • 示例:
    事务 A(trx_id=100)更新一行后,该行的 DB_TRX_ID 被标记为 100。

2.3 DB_ROLL_PTR(回滚指针)

  • 作用:
    指向 undo 日志中旧版本数据的指针,用于实现事务回滚和 MVCC。
    通过回滚指针,可以追溯数据的历史版本。
    大小:7 字节。
  • 示例:
    事务 B 查询某行时,若该行的 DB_TRX_ID 大于当前事务ID,则通过 DB_ROLL_PTR 找到可见的旧版本。

2.4 删除标记(Delete Flag)

  • 作用:
    标记该行是否被删除(逻辑删除)。
    InnoDB 的 DELETE 操作不会立即物理删除数据,而是设置此标记。
  • 清理时机:
    由 Purge 线程在事务提交后清理标记为删除的行。

3. 记录头信息(Record Header)

每条记录还包含一个 记录头,用于管理记录的元信息,主要字段如下:

  • 3.1 预留位(预留字段)
    作用:用于未来扩展,通常无实际用途。
  • 3.2 删除标记(Delete Flag)
    作用:同系统隐藏字段中的删除标记,标识该行是否被逻辑删除。
  • 3.3 最小事务ID(Min Transaction ID)
    作用:在部分行格式中,记录该行可见的最小事务ID(用于优化 MVCC 判断)。
  • 3.4 记录类型(Record Type)
    作用:标识记录的类型,例如:
    • 0:普通记录。
    • 1:B+ 树非叶子节点(索引节点)。
    • 2:伪记录(Infimum/Supremum,表示页中的最小和最大虚拟记录)。
  • 3.5 下一记录指针(Next Record Pointer)
    作用:指向页中下一条记录的物理位置,用于实现记录的链式存储。

4. 溢出页指针(对于大字段)

当记录中包含大对象(如 BLOB、TEXT 或超长 VARCHAR)时:
行溢出(Row Overflow):
数据主体存储在数据页中,超出页大小的部分存储在溢出页(Off-page)。
记录中保留 20 字节的指针,指向溢出页的地址。

5. 记录的物理存储示例

以 COMPACT 行格式为例,一条记录的完整结构如下:

| 记录头(5字节) | 用户列1 | 用户列2 | ... | DB_ROW_ID(6字节) | DB_TRX_ID(6字节) | DB_ROLL_PTR(7字节) |

总大小:记录头 + 用户列 + 隐藏字段 + 溢出页指针(若有)
image

posted @ 2025-02-26 18:31  lipu123  阅读(51)  评论(0)    收藏  举报