PG::TRDeadlockDetected: 错误:检测到死锁

25

我通过bundle exec pumactl -F config/puma.rb phased-restart重启了8个puma worker,运行良好。现在我遇到了越来越多的Postgres错误:

PG::TRDeadlockDetected: ERROR:  deadlock detected

我发现有大约50个空闲的PostgreSQL进程正在运行:

postgres: myapp myapp_production 127.0.0.1(59950) idle
postgres: myapp myapp_production 127.0.0.1(60141) idle
...
当我运行bundle exec pumactl -F config/puma.rb stop时,它们消失了。使用bundle exec pumactl -F config/puma.rb start启动应用程序后,我得到了正好16个空闲进程。(在我看来过多了八个。)
我该如何更好地管理这些进程?感谢您的帮助!

更新

我的puma.rb文件:

environment 'production'
daemonize true

pidfile 'tmp/pids/puma.pid'
state_path 'tmp/pids/puma.state'

threads 0, 1
bind 'tcp://0.0.0.0:3010'

workers 8

quiet

我对puma/ruby没有任何经验。从数据库方面来看,查看锁应该会有所帮助。https://wiki.postgresql.org/wiki/Lock_Monitoring。尝试使用提供的最后一个查询。您将知道哪个事务正在阻塞哪个事务。 - Jayadevan
没有重新启动,空闲连接会不断增加,直到应用程序因此错误崩溃:PG::ConnectionBad (FATAL: remaining connection slots are reserved for non-replication superuser connections) - Railsana
2个回答

28

我可能已经找到了解决我的问题的方法: 我在控制器之外有一些查询(自定义中间件),这似乎是导致问题的原因。

如果您在控制器之外有查询(ActiveMailer 也可能导致此问题),请将代码放在 ActiveRecord::Base.connection_pool.with_connection 块中:

ActiveRecord::Base.connection_pool.with_connection do
  # code
end

ActiveRecord的with_connection方法将数据库连接从其连接池中提供给块。当块完成时,连接会自动检查回连接池,以避免连接泄漏。

我希望这可以帮助你们中的一些人!


1
看起来这可能是由于服务器关闭时数据库连接没有被关闭导致的。https://github.com/puma/puma/issues/59 在那个问题中,很多人使用ActiveRecord::ConnectionAdapters::ConnectionManagement来处理这个问题,或者你可以使用Puma的on_restart钩子自己解决。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接