繁体   English   中英

如何调试卡在数据库事务中的红宝石进程?

[英]How do I debug a ruby process stuck in a db transaction?

我在一个相当大的Rails应用程序中运行了一些ruby后台处理。 后台处理由sidekiq gem执行。 有时我会遇到一种非常奇怪的行为,它会变成死亡螺旋。

一些相对简单的作业,对连接的postgresql数据库中的单个记录执行简单的UPDATE ,以某种方式永远不会成功。 他们执行的查询在事务中处于waiting状态,在事务中处于空闲状态,这是因为更新查询的事务显然从不发送COMMIT 当postgresql正在等待时,发送查询的ruby后台处理似乎也是如此! 红宝石进程似乎正在挂起,等待事务从postgresql完成,因此不做任何进一步的工作。

现在我的问题是,在这种僵局的情况下,我该如何进一步调试问题根源所在? (红宝石,PostgreSQL,操作系统,网络等)

PS。 如果我通过发送SELECT pg_cancel_backend(faulty_pid)手动取消了postgresql中的挂起事务,则挂起的sidekiq / ruby​​进程会立即出现连接错误并恢复正常,继续接管工作,并且像什么都没发生一样工作。 这似乎向我表明,db和ruby之间的连接仍然可以,并且ruby进程并没有真正停滞。 但是不知何故出现了问题。

PS。 我正在运行ruby 2.4.0,rails 4.2,Postgresql 9.3,sidekiq 4.2和pg 0.20.0

这很可能与您的工作人员打开的postgres的连接从未关闭过。 如果您重试作业,则会使问题更加复杂。 为了解决这个问题,您可能希望按计划运行一个工作程序,以清除所有未关闭的连接:

class DbIdleCleanerWorker
  include Sidekiq::Worker

  sidekiq_options retry: 0

  def perform()
    sql = "SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE query != '<IDLE>' AND query NOT ILIKE '%pg_stat_activity%' AND state = 'idle'
      AND now()-pg_stat_activity.query_start > interval '1 minutes'
    ORDER BY query_start desc;"
    ActiveRecord::Base.connection.execute(sql)
  end
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM