ALTER TABLE 是什么
结构变更操作。同一句话的代价可能天差地别:MySQL 支持 INSTANT 与 INPLACE 算法来减少锁表时间,PostgreSQL 大多数 DDL 会短暂持有 ACCESS EXCLUSIVE 锁——能立刻拿到就很快,拿不到就会排在已有查询后面,把后续请求一起堵住。
基本信息
| MySQL 算法 | ALGORITHM=INSTANT / INPLACE / COPY,可显式指定 |
|---|---|
| MySQL 锁选项 | LOCK=NONE 表示不阻塞读写,不支持时直接报错 |
| PostgreSQL 锁 | 多数 ALTER 需要 ACCESS EXCLUSIVE 锁 |
| PG 加列 | 加可空列是元数据操作;PG 11+ 加常量默认值同样是元数据操作 |
| PG 改类型 | 常需要重写整表并重建索引 |
| 通用护栏 | 设置 lock_timeout,拿不到锁就退出而不是排队 |
MySQL 指定算法
MySQL 指定算法
ALTER TABLE orders
ADD COLUMN memo VARCHAR(255) NULL, -- 加可空列
ALGORITHM=INPLACE,
LOCK=NONE; -- 不支持时直接报错,便于测试阶段暴露风险
-- 不指定 ALGORITHM 时由优化器自行选择,可能退化成 COPY 拷贝整表
-- 上线前先在预发环境用同样的语句验证一次PostgreSQL 注意锁等待
PostgreSQL 注意锁等待
-- 先设锁等待上限,避免把后续请求一起堵住
SET lock_timeout = '3s';
ALTER TABLE orders ADD COLUMN memo text; -- 元数据操作,很快
ALTER TABLE orders ADD COLUMN cnt int NOT NULL DEFAULT 0; -- PG 11+ 同样只改元数据
ALTER TABLE orders ALTER COLUMN amount TYPE numeric(14,2); -- 通常需要重写整表变更类型与代价
| 变更类型 | MySQL 8 | PostgreSQL |
|---|---|---|
| 加可空列 | INSTANT,很快 | 元数据操作,很快 |
| 加带默认值的列 | 视版本与默认值而定 | 11+ 常量默认值也是元数据操作 |
| 改列类型 | 多数需要重建表 | 通常重写整表并重建索引 |
| 加索引 | INPLACE,一般不阻塞写入 | 默认阻塞写;可用 CONCURRENTLY 不阻塞 |
| 加 NOT NULL 约束 | 需要校验全表 | 可先加 NOT VALID 再单独校验 |
典型使用场景
- 业务迭代加字段:新增备注与扩展字段
- 加索引提升查询性能:安排到低峰执行
- 调整字段类型或长度:应对业务量增长
- 拆分大表:配合在线工具或影子表方案
- 加约束保证数据质量:注意校验开销
- 归档后清理列:删除不再使用的冗余字段
PostgreSQL 可以用 CREATE INDEX CONCURRENTLY 建索引而不阻塞写入,代价是耗时更长、失败会留下无效索引需要清理;MySQL 建索引通常走 INPLACE,但仍会消耗大量 IO 与 CPU,建议低峰执行。
DDL 排在长事务后面会连锁阻塞:一条长查询持锁不释放时,ALTER 会一直等,后续所有请求又排到 ALTER 之后。执行前先设置 lock_timeout,并确认没有长事务与长查询在跑。