<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>MuduDB on 欢迎来到我的空间</title>
    <link>https://ybbh.github.io/post/mududb/</link>
    <description>Recent content in MuduDB on 欢迎来到我的空间</description>
    <generator>Hugo</generator>
    <language>cn</language>
    <copyright>Copyright © 2025, Guo Hua.</copyright>
    <lastBuildDate>Mon, 18 May 2026 14:51:04 +0800</lastBuildDate>
    <atom:link href="https://ybbh.github.io/post/mududb/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>数据库不应只是操作系统上的一个进程</title>
      <link>https://ybbh.github.io/post/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%8D%E5%BA%94%E5%8F%AA%E6%98%AF%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%B8%8A%E7%9A%84%E4%B8%80%E4%B8%AA%E8%BF%9B%E7%A8%8B/</link>
      <pubDate>Mon, 18 May 2026 14:51:04 +0800</pubDate>
      <guid>https://ybbh.github.io/post/%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%8D%E5%BA%94%E5%8F%AA%E6%98%AF%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%B8%8A%E7%9A%84%E4%B8%80%E4%B8%AA%E8%BF%9B%E7%A8%8B/</guid>
      <description>&lt;h1 id=&#34;数据库不应只是操作系统上的一个进程&#34;&gt;数据库不应只是操作系统上的一个进程&lt;/h1&gt;&#xA;&lt;h2 id=&#34;是时候重新审视数据库与操作系统的边界了&#34;&gt;是时候重新审视数据库与操作系统的边界了&lt;/h2&gt;&#xA;&lt;p&gt;长期以来，“数据库运行在操作系统之上”几乎是一个不需要解释的默认设定。操作系统负责进程、线程、文件系统、网络、内存和设备管理；数据库负责查询、事务、索引、缓存、并发控制和恢复。这个分工清晰、稳定，也支撑了过去几十年的数据库工程实践。&lt;/p&gt;&#xA;&lt;p&gt;但这个默认设定正在变得越来越值得讨论。&lt;/p&gt;&#xA;&lt;p&gt;问题并不在于 Linux 不好，也不在于 PostgreSQL、MySQL、RocksDB 这类系统不够优秀。真正的问题是：通用操作系统和现代数据库系统的优化目标正在出现分叉。&lt;/p&gt;&#xA;&lt;p&gt;操作系统强调通用性、隔离性、兼容性、可维护性和公平调度；数据库则越来越关注低尾延迟、可预测执行、事务一致性、直接 I/O 路径，以及对硬件行为的精细控制。二者都在进步，但它们的目标函数并不完全一致。&lt;/p&gt;&#xA;&lt;p&gt;如果数据库只是一个普通应用，运行在操作系统之上当然合理。但现代数据库早已不是普通应用。它自己管理缓存，自己管理并发，自己设计日志和恢复，自己实现调度和资源控制，在很多关键路径上甚至还要绕过操作系统提供的默认机制。&lt;/p&gt;&#xA;&lt;p&gt;到了这个阶段，我们至少应该重新问一句：&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;继续把数据库作为一个普通用户态程序运行在通用操作系统之上，仍然是最合适的系统结构吗？&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;1-数据库从来没有完全信任操作系统抽象&#34;&gt;1. 数据库从来没有完全信任操作系统抽象&lt;/h2&gt;&#xA;&lt;p&gt;从工程实现看，数据库和操作系统之间一直有一种微妙关系：数据库使用操作系统，但并不完全依赖操作系统。&lt;/p&gt;&#xA;&lt;p&gt;数据库通常不会简单地把内存管理交给操作系统 page cache，而是自己实现 buffer pool。数据库不会只依赖操作系统的文件写入语义，而是自己实现 WAL、checkpoint、group commit 和崩溃恢复。数据库也不会把并发控制交给操作系统锁，而是自己实现 latch、lock manager、MVCC 和事务调度。&lt;/p&gt;&#xA;&lt;p&gt;这不是数据库工程师喜欢重复造轮子，而是因为操作系统提供的是通用抽象，而数据库需要的是更强的语义约束和更可预测的执行行为。&lt;/p&gt;&#xA;&lt;p&gt;操作系统看到的是线程、文件、页、socket 和 block device。数据库看到的是事务、日志、脏页、索引、锁等待、查询计划和恢复点。二者面对的是同一台机器，但理解系统状态的方式并不一样。&lt;/p&gt;&#xA;&lt;p&gt;这种差异过去也存在，只是没有现在这么尖锐。硬件慢、并发低、系统规模小的时候，多一层抽象、多几次上下文切换、多一点调度不确定性，未必会成为决定性问题。但在多核、NVMe、RDMA、云存储和低延迟在线服务成为常态之后，这些抽象差异会被迅速放大，最终变成性能问题、稳定性问题，甚至可靠性问题。&lt;/p&gt;&#xA;&lt;h2 id=&#34;2-linux-调度变化影响-postgresql问题不只是一次性能回退&#34;&gt;2. Linux 调度变化影响 PostgreSQL：问题不只是一次性能回退&lt;/h2&gt;&#xA;&lt;p&gt;Phoronix 报道过一个很典型的案例：AWS 工程师在 Linux 7.0 开发周期中发现，PostgreSQL 在 Graviton4 机器上的性能出现明显下降，吞吐量大约只有此前内核版本的一半。相关分析认为，问题与 Linux 抢占模型变化有关，PostgreSQL 在用户态 spinlock 上花费了更多时间。&lt;/p&gt;&#xA;&lt;p&gt;参考链接：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.phoronix.com/news/Linux-7.0-AWS-PostgreSQL-Drop&#34;&gt;https://www.phoronix.com/news/Linux-7.0-AWS-PostgreSQL-Drop&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这个案例值得关注，并不只是因为“性能下降了一半”这个数字醒目，而是因为它暴露了数据库和操作系统之间一种长期存在的隐含依赖。&lt;/p&gt;&#xA;&lt;p&gt;PostgreSQL 的不少关键路径依赖用户态锁和短临界区。理想情况下，锁持有者会很快完成工作并释放锁，其他线程只需要短暂等待。但如果操作系统在不合适的时机抢占了锁持有者，等待者就可能在用户态空转。单次等待看起来很小，放到高并发事务系统中，就可能被放大成吞吐下降和尾延迟恶化。&lt;/p&gt;&#xA;&lt;p&gt;从操作系统角度看，调整抢占模型可能有充分理由。内核要面对的是各种不同类型的负载，它需要维护通用性、公平性和长期可维护性。&lt;/p&gt;&#xA;&lt;p&gt;但从数据库角度看，这种变化可能破坏多年调优出来的并发行为。数据库以为自己控制了锁和调度，实际上仍然依赖内核调度器的具体行为。内核并不理解这些用户态锁背后的事务语义，也不会承诺永远维持一种对数据库友好的时序。&lt;/p&gt;&#xA;&lt;p&gt;所以这个案例真正值得讨论的地方在于：&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;数据库的性能关键路径建立在操作系统调度语义之上，而这些语义并不是为数据库事务处理专门设计的。&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;这不只是某个内核版本的偶然问题。只要数据库仍然作为普通进程运行在通用操作系统上，它就必须持续适配外部调度策略的变化。&lt;/p&gt;&#xA;&lt;h2 id=&#34;3-fsync-事件说明文件接口和事务持久化之间存在语义裂缝&#34;&gt;3. fsync 事件说明：文件接口和事务持久化之间存在语义裂缝&lt;/h2&gt;&#xA;&lt;p&gt;性能问题已经足够麻烦，可靠性问题更复杂。PostgreSQL 的 fsync failure 事件就是一个典型例子。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
