MySQL 8.0Notes

第 10 章:表与元数据

zjc 于 2026-01-10 发布

这是《MySQL 8.0 源码与内核实战》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 MySQL 8.0 使用事务性数据字典存储表、列、索引、字符集和约束等元数据。Server 层表缓存、MDL 和 InnoDB 字典缓存共同决定 DDL 与 DML 的并发行为。

10.1 元数据演进

版本 方式
5.7 及以前 .frm 等文件保存表定义
8.0 DD 表存储元数据

8.0 带来:

  1. 原子 DDL;
  2. 元数据事务化;
  3. 支持更完整的字符集和 collation;
  4. 移除 .frm
  5. 统一系统表存储。

原子 DDL 表示 DDL 的数据字典更新整体提交或回滚,不等价于所有 DDL 都不锁表或不重建表。

10.2 核心对象

对象 职责
DD tables 存储元数据
Dictionary Client Server 层访问接口
dd::Table 表定义
dd::Column 列定义
dd::Index 索引定义
TABLE_SHARE 可共享表定义
TABLE 每个表实例的运行时对象
InnoDB dict cache 引擎层缓存

10.3 表缓存

open_tables
  -> table cache hit?
     |-- yes: reuse TABLE
     +-- no: load DD definition
        -> create TABLE
           -> open handler

相关参数:

参数 说明
table_open_cache 表缓存数量
table_open_cache_instances 缓存分区
table_definition_cache 表定义缓存
open_files_limit 文件句柄上限

观测:

SHOW GLOBAL STATUS LIKE 'Open_%';
SHOW GLOBAL STATUS LIKE 'Opened_%';

10.4 MDL

元数据锁保护表结构在语句或事务期间不被不兼容 DDL 破坏。

常见锁:

类型 场景
SHARED_READ SELECT
SHARED_WRITE DML
SHARED_UPGRADABLE 部分 DDL 前置阶段
EXCLUSIVE 阻塞读写

问题场景:

长事务持有 SHARED_READ
  -> DDL 等待 EXCLUSIVE
     -> 后续 DML 排队

排查:

SELECT * FROM performance_schema.metadata_locks;
SELECT * FROM sys.schema_table_lock_waits;

10.5 DDL 阶段

通用阶段:

acquire MDL
  -> prepare
     -> algorithm decision
        -> prepare output table
           -> alter table data if needed
              -> commit DD
                 -> release locks

ALGORITHM:

算法 说明
INSTANT 只改元数据,受版本和操作限制
INPLACE 引擎内执行,可能允许并发 DML
COPY 重建表并复制数据

指定不支持的算法会报错:

ALTER TABLE t ADD COLUMN c INT, ALGORITHM=INSTANT;

10.6 LOCK 策略

ALTER TABLE t ADD INDEX idx_c(c), ALGORITHM=INPLACE, LOCK=NONE;
含义
NONE 允许并发 DML
SHARED 允许读,阻塞写
EXCLUSIVE 阻塞读写

实际支持由操作、索引类型、版本和引擎决定:

SHOW ALGORITHM STATUS;

或查看 information_schema.innodb_alter_algorithm,取决于版本支持情况。

10.7 临时表

SQL 层临时表:

  1. 会话可见;
  2. 不进入 binlog 主流复制路径;
  3. 可由引擎内部临时表或用户 TEMPORARY 表;
  4. DDL 和 MDL 行为不同。

内部临时表可能由内存引擎转为磁盘 InnoDB 临时表,受 internal_tmp_mem_storage_enginetmp_table_sizemax_heap_table_size 等影响。

10.8 字符集与排序规则

元数据记录:

  1. 表默认字符集;
  2. 列字符集;
  3. collation;
  4. 表达式推导规则。

示例:

CREATE TABLE t(
  a VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,
  b VARCHAR(32)
) DEFAULT CHARSET=utf8mb4;

collation 影响:

  1. 等值比较;
  2. 排序;
  3. 索引查找;
  4. 前缀匹配;
  5. 函数结果推导。

10.9 DDL 故障排查

现象 方向
DDL 等待 metadata lock 长事务、表缓存
DDL 后查询计划变化 统计、索引、字符集
instant 失败 操作或版本不支持
inplace 长时间 在线 DDL 日志和重建
copy 占用磁盘 临时表空间
DDL 卡在 finalize 锁和后台操作

处理:

  1. 找 waiting thread;
  2. 找 blocking thread;
  3. 评估长事务;
  4. 使用低峰窗口;
  5. 预留磁盘;
  6. 大表使用 gh-ost/pt-osc 评估;
  7. 记录回滚方案。

本章小结

表与元数据链路覆盖 DD 存储、表定义缓存、运行时 TABLE、handler 打开和 MDL。理解这条链路能解释 DDL 等待、原子性、并发 DML 和统计刷新行为,也是后续读 DDL 源码的基础。

思考题

  1. MySQL 8.0 原子 DDL 解决了什么问题?
  2. TABLE_SHARETABLE 的区别是什么?
  3. 为什么长事务会阻塞 DDL 并间接阻塞后续 DML?
  4. INSTANT、INPLACE、COPY 的核心差异是什么?
  5. collation 如何影响索引查找?