PG:: TRDeadlockDetected: ОШИБКА: обнаружен тупик

Я перезапускаю 8 работников puma через bundle exec pumactl -F config/puma.rb phased-restart, что отлично работает. Теперь я получаю все больше ошибок postgres:

PG::TRDeadlockDetected: ERROR:  deadlock detected

Я нашел около 50 простаивающих процессов postgres:

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

Ответы

Ответ 1

Возможно, я нашел решение моего вопроса: У меня были некоторые запросы за пределами моих контроллеров (настраиваемое промежуточное ПО), которые, похоже, вызвали эту проблему.

Если у вас есть запросы вне контроллеров (ActiveMailer также может вызвать эту проблему), поместите свой код в блок ActiveRecord::Base.connection_pool.with_connection:

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

Метод ActiveRecords with_connection дает соединение с базой данных из своего пула в блок. Когда блок завершается, соединение автоматически проверяется обратно в пул, избегая утечек соединения.

Надеюсь, это поможет некоторым из вас!

Ответ 2

Похоже, это связано с тем, что соединения с базой данных не закрываются при завершении работы сервера. https://github.com/puma/puma/issues/59 Многие люди в этой проблеме используют ActiveRecord:: ConnectionAdapters:: ConnectionManagement, чтобы справиться с этим, или вы можете самостоятельно используя Puma on_restart.