自省 自行 自醒

别把数据库技术写成饭圈文学,降智

Word count: 1.5kReading time: 5 min
2026/06/19
loading

前言

今早在某群里看到一篇名为《PG 的 DDL 还吹?和 MySQL 逐条对线》的文章,被标题吸引,点进去看了一下, 笔者原本以为会是一篇从原理剖析再到最佳实践的鸿篇巨制,实际却大跌眼镜,像被强行喂了一坨。

简而言之,这不是一篇严肃的数据库对比文章,更像是一篇披着技术外衣的 MySQL 爽文。并且这篇文章不是简单地错,而是”选择性正确”,一种非常明显的倾向性叙事。原文如下:

鸡贼在哪里

通篇看下来,这篇文章最大的问题不是不知道 DDL,而是十分会挑角度。

第一,它把 MySQL 的最佳实践当成默认能力,把 PostgreSQL 的默认锁语义当成全部能力。

MySQL 这边上来就是 ALGORITHM=INSTANTALGORITHM=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 CONCURRENTLYNOT VALID、事务性 DDL,被它写得像是补丁、绕路、不得已而为之。

到了 MySQL 这边,pt-oscgh-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 仍然会隐式提交。

小结

作为技术人员,有时间写这种流量水文,不如多花点时间研究两边的设计取舍。取长补短,攻守兼备,才是正道。

别把数据库技术写成饭圈文学,降智。

CATALOG
  1. 1. 前言
  2. 2. 鸡贼在哪里
  3. 3. 反复强调的 AccessExclusiveLock
  4. 4. 事务性 DDL
  5. 5. 小结