前言
今早在某群里看到一篇名为《PG 的 DDL 还吹?和 MySQL 逐条对线》的文章,被标题吸引,点进去看了一下, 笔者原本以为会是一篇从原理剖析再到最佳实践的鸿篇巨制,实际却大跌眼镜,像被强行喂了一坨。
简而言之,这不是一篇严肃的数据库对比文章,更像是一篇披着技术外衣的 MySQL 爽文。并且这篇文章不是简单地错,而是”选择性正确”,一种非常明显的倾向性叙事。原文如下:

鸡贼在哪里
通篇看下来,这篇文章最大的问题不是不知道 DDL,而是十分会挑角度。
第一,它把 MySQL 的最佳实践当成默认能力,把 PostgreSQL 的默认锁语义当成全部能力。
MySQL 这边上来就是 ALGORITHM=INSTANT、ALGORITHM=INPLACE LOCK=NONE,看起来成熟、丝滑、毫秒级、不阻塞。
PostgreSQL 这边则反复强调 AccessExclusiveLock,并且偷换概念,重锁 = 阻塞,看起来笨重、原始、动不动就锁表。这就像一边拿精装修样板间,一边拿毛坯房验收图,然后得出结论:前者吊打后者。
第二,它把 PostgreSQL 的强锁直接翻译成”业务阻塞”,却把 MySQL 的 MDL 写得像空气一样。
PostgreSQL 的 AccessExclusiveLock 重不重?当然重。会不会和 SELECT 冲突?会。生产变更要不要谨慎?必须谨慎。
但 MySQL 的 Online DDL 就没有锁了吗?MDL 不算锁?长事务卡住 metadata lock 不算事故?DDL 等待 exclusive metadata lock 时阻塞后续请求不算线上风险?选择性失明。
第三,它把 PostgreSQL 的安全机制写成”麻烦”,却把 MySQL 的外部工具生态写成”成熟。
PostgreSQL 的 CREATE INDEX CONCURRENTLY、NOT VALID、事务性 DDL,被它写得像是补丁、绕路、不得已而为之。
到了 MySQL 这边,pt-osc、gh-ost 又成了成熟生态。
这套话术十分鸡贼:PG 内核里的安全机制,叫麻烦;MySQL 外部工具绕出来的方案,叫成熟。这是双标。
第四,它拿”100GB 表 + NVMe SSD”的测试结果做结论,却不给关键上下文。
表结构是什么?行宽多少?有没有二级索引?有没有并发写入?有没有长事务?binlog/WAL 怎么开?checkpoint 参数如何?buffer 和 maintenance memory 配置是什么?测试时业务压力如何?
这些都没有。脱离上下文谈 DDL 性能,这是耍流氓,标题党。
反复强调的 AccessExclusiveLock
文章里反复强调 PostgreSQL 的 AccessExclusiveLock,很多 DDL 的重锁窗口其实本身很短,真正危险的是锁等待:前面有长事务、长查询、未提交事务,DDL 排队;DDL 一旦排队,后续请求又被锁队列影响,最后形成业务阻塞。既然知道这种危害,难道你在做此类操作前不会设置 lock_timeout?这个基本的操作规范都不知道,还是洗洗睡吧。MySQL 也有 metadata lock。Online DDL 不是全程无锁,更不是天然免疫长事务。一个长事务挂在那里,DDL 等 MDL,后续请求再被等待中的 exclusive MDL 卡住,这种事故 MySQL DBA 难道没见过?
另外,MySQL 的 ALGORITHM=INSTANT 确实是好东西。
添加列、删除列,在满足条件时,只改数据字典,不扫表、不重写数据页,速度极快。这是 MySQL 8.0/8.4 在 DDL 工程体验上的重要优势,没什么好否认的。
但 INSTANT 不是魔法。它不是所有表都能用,压缩行格式、全文索引、临时表、系统表、最大列数、最大 row version 等,都可能成为限制。达到 row version 上限以后,继续 ADD COLUMN / DROP COLUMN 也可能失败,最后还是要 rebuild。
文中也是只字不提,只讲”毫秒级、不堵”,典型的广告口径。
其次,INPLACE 的意思不是不动数据,而是不走 MySQL Server 层传统 COPY 算法,尽量由 InnoDB 内部完成。它可能扫描表,可能构建索引,可能重组数据,也可能 rebuild table。所以看到 ALGORITHM=INPLACE 就以为万事大吉,只能说明你还没被生产教育过。
其次,还有加字段,请先去了解一下 PG11 以后的行为,拿老黄历批评新版本,是很多数据库争论里最常见的低级操作。
再之,文章拿 int -> bigint 做例子,说两边都会 rewrite。
这个例子本身没问题,很多涉及物理存储格式变化的类型修改,两边确实都很重。
但问题是,字段类型修改是一个大类,不是只有 int -> bigint。在 PG 中,字段类型由小改大基本都不会重写,那杠精又来了,由大改小?那请再去了解下 text/varchar 的实现原理。
只挑一个最容易触发 rewrite 的例子,然后暗示 PostgreSQL 字段类型修改都差不多如此,居心叵测。
事务性 DDL
这一点是我最想笑的地方,并且文章将其放在了最后,像是”PG 唯一能翻盘的一条救命稻草”,原文最后问了一句,大意是:**你扪心自问,你在生产环境 rollback 过 DDL 吗?**笔者读到时一整个蚌埠住了,真正做过复杂迁移的人,应该很清楚这东西有多重要,迁移脚本、灰度发布、失败回滚、批量 schema 变更里,DDL 回滚简直不要太好用。
MySQL 8.0 的 Atomic DDL 解决的是崩溃一致性,不等于用户事务里可以随便 rollback DDL。很多 DDL 仍然会隐式提交。
小结
作为技术人员,有时间写这种流量水文,不如多花点时间研究两边的设计取舍。取长补短,攻守兼备,才是正道。
别把数据库技术写成饭圈文学,降智。