Skip to content

分区、归档与在线 DDL

分区解决的是大表管理和分区裁剪问题,在线 DDL 解决的是如何低风险改变表结构。它们都不是“执行一条 alter 就结束”,而是生产变更工程。

分区解决什么

一个分区表在逻辑上仍是一张表,但数据按规则落在不同分区中。典型收益:

  • 查询带分区键时可以裁剪无关分区。
  • 按时间删除历史分区通常比大批量 delete 更可控。
  • 备份、归档和生命周期管理更清晰。

它不能自动解决低效 SQL、热点写入和所有索引问题,也不等于分库分表。

常见分区类型

sql
create table audit_log (
  id bigint not null,
  created_at datetime not null,
  content json not null,
  primary key (id, created_at)
)
partition by range columns(created_at) (
  partition p202608 values less than ('2026-09-01'),
  partition p202609 values less than ('2026-10-01'),
  partition pmax values less than (maxvalue)
);
  • range / range columns:时间和递增范围。
  • list:有限业务区域或类别。
  • hash / key:相对均匀分布。

分区键必须与高频过滤和生命周期一致。唯一键与分区键存在版本相关约束,设计前必须验证目标版本。

验证分区裁剪

sql
explain
select id
from audit_log
where created_at >= '2026-08-01'
  and created_at < '2026-09-01';

select table_name, partition_name, table_rows
from information_schema.partitions
where table_schema = database()
  and table_name = 'audit_log';

若查询没有携带分区键,仍可能扫描大量分区。对分区键套不利于推导的函数,也可能影响裁剪。

归档与删除策略

历史数据治理优先明确:在线保留多久、归档保存多久、是否允许查询、合规删除要求是什么。常见路线:

  1. 在线表保留热数据。
  2. 通过稳定主键或时间窗口小批迁移。
  3. 校验行数、校验和与业务抽样。
  4. 灰度切换历史查询。
  5. 删除或丢弃旧分区。
  6. 保留审计记录和可回滚窗口。

大批 delete 会产生 undo、redo、binlog、锁和复制压力。分批执行也要监控延迟,并避免依赖不稳定的无序 limit

MySQL DDL 算法

不同版本和操作可能使用:

  • INSTANT:主要修改元数据,通常最快,但有功能限制。
  • INPLACE:尽量不复制整表,但可能扫描或重建索引,仍会消耗 IO/CPU。
  • COPY:复制并重建表,耗时和空间风险最大。

锁级别可能是 NONESHAREDEXCLUSIVE。名字叫在线不等于零影响:DDL 开始和结束通常仍需获取元数据锁,长事务可能使它等待,排队后的 DDL 又会阻塞后续请求。

sql
alter table orders
  add column source varchar(32) null,
  algorithm = instant;

若指定算法不受支持,应该让语句失败后重新评估,避免生产静默退化成高风险复制表。

元数据锁 MDL

会话访问表时会持有 MDL 到事务结束。一个忘记提交的查询事务可能阻塞 DDL:

sql
select *
from performance_schema.metadata_locks
where object_schema = 'app_db'
  and object_name = 'orders';

处理原则不是直接杀所有连接,而是确认阻塞链、事务用途、回滚成本和业务影响,再终止根阻塞者或取消 DDL。

大表变更清单

变更前:

  • 在同版本和相近数据量环境验证算法、耗时与额外空间。
  • 检查长事务、外键、触发器、复制拓扑和磁盘余量。
  • 设定锁等待超时、观测指标、暂停阈值和回滚方案。
  • 确认新旧应用版本对字段同时兼容。

变更中:

  • 监控 QPS、P99、CPU、IO、锁等待、复制延迟和磁盘。
  • 避免与备份、批任务和业务高峰重叠。
  • 在线变更工具必须理解触发器、外键、切表和失败清理机制。

变更后:

  • 验证表定义、索引、行数和核心查询计划。
  • 确认副本全部应用完成。
  • 清理临时对象前保留足够观察窗口。

面试标准回答

分区和分库分表有什么区别

分区仍由一个 MySQL 实例管理,SQL 和事务边界基本保持单表语义,主要改善裁剪和生命周期管理;分库分表把数据分布到多个物理表或实例,能突破单机容量和吞吐,但引入路由、跨分片查询、全局 ID 和分布式事务问题。

Online DDL 为什么还可能阻塞

即使数据重建阶段允许并发读写,DDL 在准备和提交阶段仍可能需要 MDL;长事务持有表的元数据锁会让 DDL 等待。DDL 排在锁队列中后,后续业务请求也可能排队,因此必须监控长事务和锁等待。