AWS 工程师实测:升级 Linux 7.0 后,PostgreSQL 吞吐量暴跌 49%。内核开发者的回应是——"这不是我的问题"。
一次「例行升级」引发的血案
2026 年 4 月 3 日,一个普通的周五。
AWS 工程师 Salvatore Dipietro 像往常一样跑着 PostgreSQL 的性能基准测试。他用的是一台 96 核的 Graviton4 实例——AWS 自研 ARM 芯片的旗舰,配上 12 块 IO2 SSD 组成 RAID0,堪称数据库跑分的「梦之机」。
唯一的变量是内核版本:Linux 7.0-rc6。
结果出来的那一刻,他以为自己看错了:
一半的性能,凭空蒸发了。
这不是某个边缘场景的微小波动。这是全球最流行的开源数据库,在即将成为 Ubuntu 26.04 LTS 默认内核的版本上,吞吐量直接减半。
而更令人震惊的是——内核开发者认为这不是 bug,而是 feature。
凶手是谁?
Dipietro 没有慌。作为 AWS 的内核性能工程师,他做了每个老手都会做的事:git bisect。
经过系统的二分排查,他精确定位到了一个 commit:
commit 7dadeaa6e851Author: Peter Zijlstra (Intel)Title: "sched: Further restrict the preemption modes"
这个提交做了一件看似「技术清理」的事情:在所有现代 CPU 架构上,移除了 PREEMPT_NONE 调度选项。
什么意思?
Linux 内核抢占模型演进

简单来说:
- PREEMPT_NONE(从不抢占):线程一旦拿到 CPU,除非自己主动让出,否则不会被打断。这是服务器和数据库的最爱——吞吐量最大化。
- PREEMPT_LAZY(懒惰抢占):内核「可以」在某些时机打断你,但不会太激进。这是 Linux 7.0 的新默认值。
Peter Zijlstra 的 commit 直接把 PREEMPT_NONE 从 arm64、x86、powerpc、riscv、s390、loongarch 六大架构上全部删除。
20 年来服务器内核的默认行为,一夜之间被改写。
PostgreSQL受伤最深
要理解这个问题,需要先了解 PostgreSQL 的一个核心设计:Buffer Pool 管理。
PostgreSQL Buffer Pool 与 Spinlock 机制

PostgreSQL 的 Buffer Pool 是所有数据页面的内存缓存。当需要淘汰旧页面、换入新页面时,必须通过 StrategyGetBuffer() 函数,而这个函数内部用了一把 spinlock(自旋锁)来保护关键数据结构。
Spinlock 的设计哲学很简单:我只锁几微秒,你等一下就好。它不会让线程睡眠,而是让等待者在原地「自旋」——不断检查锁是否释放。
这在 PREEMPT_NONE 下完美运作:
PREEMPT_NONE vs PREEMPT_LAZY 下的 Spinlock 行为
这就是灾难的根源。
在 PREEMPT_NONE 下,持有 spinlock 的线程不会被打断,几微秒就能完成操作。但在 PREEMPT_LAZY 下,调度器可以在线程持锁期间将其抢占。锁没释放,但持锁者被挂起了——其他所有等待这把锁的线程只能在原地空转,白白烧 CPU。
在 96 核、1024 并发的场景下,这种效应呈指数级放大:
55% 的 CPU 时间花在了 spinlock 空转上。 你的 96 核服务器,有 53 个核在做无用功——等待一个被调度器抢走的线程回来释放锁。
邮件列表上的「甩锅大战」
故事到这里,如果只是一个技术 bug,修复就完了。但真正精彩的是接下来发生的事。
第一回合:AWS vs Intel
Dipietro 提交了 revert 补丁,希望恢复 PREEMPT_NONE。Zijlstra 的回应很直接:
"The fix here is to make PostgreSQL make use of rseq slice extension."
(修复方案是让 PostgreSQL 使用 rseq 时间片扩展。)
不是我内核的问题,是你数据库该改了。
第二回合:PostgreSQL 核心开发者的「神转折」
事情在 PostgreSQL 核心开发者 Andres Freund 介入后出现了戏剧性转折。
Freund 在自己的 x86 服务器(2x Xeon Gold 6442Y,48 核)上尝试复现,结果发现:
"I don't see such a regression... basically no time spent in s_lock() (< 0.2%)."
他复现不了!但经过深入排查,他发现了关键变量:Huge Pages(大页内存)。
Dipietro 的 AWS 测试脚本没有启用 huge pages。当 Freund 也禁用 huge pages 后,终于复现了问题。他的结论相当犀利:
"I don't see a reason to particularly care about the regression if that's the sole way to trigger it. Using a buffer pool of ~100GB without huge pages is not an interesting workload."
(如果只有这种方式才能触发,我不觉得需要特别关注这个回归。100GB 的 buffer pool 不用 huge pages,这不是一个有意义的工作负载。)
PostgreSQL 自己的核心开发者,站到了内核开发者那边。
Huge Pages 是关键

不用 huge pages 时,100GB 的共享内存被切成约 2600 万个 4KB 小页面。当 PostgreSQL 进程首次访问某个页面时,会触发 minor page fault(缺页中断),进入内核态处理。如果此时恰好持有 spinlock,PREEMPT_LAZY 就有机会在内核态中抢占这个线程——锁被带走,其他线程全部空转。
用了 huge pages,同样的内存只需要约 5 万个 2MB 页面,TLB miss 和 page fault 大幅减少,持锁期间几乎不会进入内核态,PREEMPT_LAZY 也就无从下手。
社区的治理哲学碰撞
这场争论的本质,远不止一个技术 bug。它暴露了 Linux 内核社区和 PostgreSQL 社区在治理哲学上的深层分歧。
Linux 内核社区:「向前看」的激进派

Zijlstra 的立场很明确:PREEMPT_NONE 是历史遗留,PREEMPT_LAZY 是更优雅的统一模型。用户态程序如果依赖「不被抢占」的假设,那是用户态的问题。内核提供了 rseq(restartable sequences)机制,应用应该主动适配。
内核邮件列表上有人甚至说 PostgreSQL 的 spinlock 用法是 "seriously egregious things"(严重恶劣的做法)。
PostgreSQL 社区:「稳定压倒一切」的保守派

PostgreSQL 的核心代码库有 30 年历史。它的 buffer manager 和 spinlock 设计是在「内核不会随意抢占用户态线程」的假设下构建的。要求 PostgreSQL 集成 rseq 意味着:
有趣的是,PostgreSQL 核心开发者 Andres Freund 的态度比较务实。他没有站在「PostgreSQL 无辜」的立场上,而是指出了 AWS 测试配置的问题(不用 huge pages),并表示愿意测试 rseq:
"I'll look at trying out the rseq slice extension in a bit, it looks like it nice for performance regardless of using spinlocks."
Zijlstra 对此表示感谢,并提到 Oracle 的数据库团队已经在使用 rseq 且效果良好。
这本质上是两种开源治理模式的碰撞:
谁对谁错?
说实话,双方都有道理,双方也都有问题。
内核方面
有道理的地方:
- PREEMPT_NONE 确实是历史包袱,统一调度模型是正确方向
- 用户态 spinlock 依赖「不被抢占」本身就是脆弱的假设
有问题的地方:
- 在 stable release 前两周才被发现如此严重的回归
PostgreSQL 方面
有道理的地方:
有问题的地方:
- AWS 的测试配置确实不够合理(不用 huge pages)
- PG 19 已经移除了这个路径上的 spinlock,说明社区自己也认为需要改
一个时代的终结
这场争论的深层意义在于:Linux 内核正在告别「对用户态无条件友好」的时代。
过去 20 年,PREEMPT_NONE 是服务器内核的默认选择。无数应用——不只是 PostgreSQL,还有 MySQL、Oracle、Redis,以及任何使用用户态 spinlock 的程序——都在这个假设下构建和优化。
Linux 7.0 打破了这个假设。它说:内核有权在任何时候抢占你的线程,如果你不想被抢占,请主动告诉内核。
这是一个更「正确」的模型,但也是一个更「危险」的转变。
就像 Zijlstra 在 commit message 里写的:
"Keep the patch minimal in case of hard to address regressions that might pop up."
他知道会有回归。他只是没想到,第一个中枪的会是 PostgreSQL。
参考资料:
- Linux 7.0 Cuts PostgreSQL Performance in Half - WinBuzzer
- Kernel Mailing List: Restore PREEMPT_NONE as default
- 30 years of PostgreSQL buffer manager locking design evolution
- Revisiting the kernel's preemption model - LWN.net
- Half as Fast on Linux 7 - Scaling Postgres