Hacker News 中文摘要

RSS订阅

当Sigterm失效时:Postgres之谜 -- When Sigterm Does Nothing: A Postgres Mystery

文章摘要

ClickPipes团队在处理Postgres逻辑复制槽创建时遇到一个棘手问题:查询耗时异常且无法通过常规方法终止,导致客户不满并威胁生产数据库的稳定性。通过深入调查,发现这是Postgres的一个bug。文章详细介绍了问题的排查过程、解决方案以及与Postgres社区合作的经验。

文章总结

文章标题:当SIGTERM无效时:Postgres的一个谜团

主要内容总结:

  1. 问题背景

    • ClickPipes团队在Postgres的只读副本上创建逻辑复制槽时遇到了一个严重问题:某些查询耗时过长,且无法通过常规方法终止,导致客户不满并威胁生产数据库的稳定性。
  2. 初步调查

    • 通过检查pg_stat_activity表,发现创建逻辑复制槽的查询处于“active”状态,但没有等待事件,表明Postgres认为该查询并未被阻塞。
    • 尝试使用SIGINTSIGTERM信号终止该查询,但均无效。这导致复制槽无法被删除,进而可能导致WAL日志无限累积,引发存储耗尽的风险。
  3. 深入分析

    • 通过strace工具分析,发现后台进程处于一个1ms的nanosleep循环中,表明进程在等待某些事务完成。
    • 进一步研究发现,Postgres在创建逻辑复制槽时需要等待所有早于该槽创建的事务完成,以确保一致性。然而,在只读副本上,由于无法直接获取主库上的事务锁,导致进程陷入无限等待。
  4. 问题根源

    • 在只读副本上,Postgres的XactLockTableWait函数无法像在主库上那样通过锁机制高效等待事务完成,而是通过1ms的轮询循环进行等待。由于该循环未处理中断信号,导致进程无法被终止。
  5. 解决方案

    • 提交了一个补丁,在每次pg_usleep调用前添加中断检查,使得进程可以被正常终止。该补丁被Postgres社区迅速接受并向后移植到所有支持的版本中。
    • 社区成员还提出了进一步改进的建议,包括添加新的等待事件和优化只读副本上的事务等待机制。
  6. 总结与建议

    • 该问题展示了现代数据库系统在复杂场景下可能出现的边缘情况。Postgres和ClickHouse作为开源数据库,允许用户深入调查问题并提交补丁,从而共同提升系统的稳定性和性能。
    • 对于需要从Postgres复制数据到ClickHouse的用户,推荐使用ClickPipes或PeerDB,它们提供了高效的数据复制解决方案,并支持在只读副本上进行CDC操作。

图片标记: - Image 1: User Image (5).png

评论总结

  1. 关于固定睡眠时间的使用

    • 观点:在程序中使用固定的睡眠时间通常是错误的,因为它要么太长,要么太短,且无法保证程序会精确地睡眠所请求的时间。
    • 论据gsliepen 提到:“Virtually any time you put a fixed sleep in your program, it's going to be wrong.”(几乎每次在程序中使用固定睡眠时间都是错误的。)
    • 建议:使用条件变量或其他类似机制更为合适。
  2. 关于信号处理的复杂性

    • 观点:Postgres 作为长期运行的服务器进程,其信号处理机制复杂,某些循环可能无法及时处理信号。
    • 论据Joker_vD 指出:“Postgres, as any long-running 'server' process, does not run with SIGDFL as the handler for SIGTERM.”(Postgres 作为任何长期运行的“服务器”进程,不会使用 SIGDFL 作为 SIGTERM 的处理程序。)
    • 担忧eunos 表示:“With quirk like these, honestly I'm not even confident how can PostgreSQL or any software in general can be used in mission critical system.”(对于这些怪癖,老实说,我对 PostgreSQL 或任何软件在关键任务系统中的使用都没有信心。)
  3. 关于信号处理测试的重要性

    • 观点:在边缘条件下,Postgres 进程可能会忽略 SIGTERM 信号,建议在故障转移或副本维护期间测试信号处理。
    • 论据OkPin 提到:“Makes me wonder how many other Postgres processes might ignore SIGTERM under edge conditions.”(让我想知道在边缘条件下,还有多少其他 Postgres 进程可能会忽略 SIGTERM。)
    • 建议:将信号处理测试添加到混沌测试中。
  4. 关于开源项目的贡献流程

    • 观点:Postgres 和 Linux 内核等大型开源项目使用邮件列表进行贡献,虽然流程可能较为古老,但效率较高。
    • 论据bhaak 指出:“The Linux kernel works the same way.”(Linux 内核的工作方式相同。)
    • 对比bhaak 提到:“If I were a regular contributor to a big project using GitHub, me being me, I would probably look for or write myself a GitHub to e-mail gateway.”(如果我是使用 GitHub 的大型项目的常规贡献者,我可能会寻找或自己编写一个 GitHub 到电子邮件的网关。)
  5. 关于同步与异步方法的冲突

    • 观点:在异步事件驱动的上下文中使用同步的、基于锁的方法会导致问题,建议采用基于事件监听的方法。
    • 论据gpavanb 指出:“The fundamental problem is that a synchronous, lock-based approach is being used in an asynchronous, event-driven context.”(根本问题在于在异步事件驱动的上下文中使用了同步的、基于锁的方法。)
    • 建议:Postgres 团队需要重新设计,避免轮询,采用基于事件监听的方法。
  6. 关于类似问题的普遍性

    • 观点:Postgres 在其他情况下也可能表现出类似的行为,建议将解决方法推广到其他类型的故障。
    • 论据caffeinated_me 提到:“This isn't the only place Postgres can act like this, though.”(这并不是 Postgres 唯一表现出这种行为的地方。)
    • 建议:将解决方法推广到处理其他类型的故障。