[英]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.