Ошибка приложения Rails после миграции, которая не должна на него влиять

Я пытаюсь отладить проблему, которая недавно появилась в моем приложении Rails (3.0.9), когда экземпляры приложения необходимо перезапускать (не повторно развертывать), когда в базе данных выполняется непрерывная миграция. Такого раньше не было, и я не могу найти причину, по которой это должно было начаться недавно.

В моей производственной среде есть несколько серверов, каждый из которых использует разветвленные экземпляры Unicorn, и все они используют один экземпляр MySQL. Каждый экземпляр использует пул соединений 1. У меня также есть один сервер, который используется в качестве конечной промежуточной среды для тестирования на реальных данных после тестирования на промежуточной базе данных.

В прошлом мы могли запускать миграции на производственной БД без повторного развертывания или даже перезапуска производственных серверов Unicorn, если они были миграциями, которые старый код никогда не должен был видеть. Например, добавление нового необязательного поля в существующую таблицу - код, развернутый на промежуточном сервере, будет записывать в него данные, но существующие серверы могут безоговорочно игнорировать его и продолжать использовать БД так же, как и до готовы запустить новый код в производство.

Однако в последнее время мы наблюдаем исключение, которое выдается производственными серверами после выполнения миграции, но только когда он пытается вставить новую строку в измененную таблицу. Все остальные части приложения и все другие таблицы не затрагиваются, но как только есть вставка, мы получаем это:

NoMethodError: undefined method `name' for nil:NilClass

[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:56:in `visit_Arel_Nodes_InsertStatement'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:55:in `map'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:55:in `visit_Arel_Nodes_InsertStatement'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:15:in `send'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:15:in `visit'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/visitor.rb:5:in `accept'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:18:in `accept'
[GEM_ROOT]/bundler/gems/rails-83fb5552b6ab/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb:111:in `with_connection'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/visitors/to_sql.rb:16:in `accept'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/tree_manager.rb:20:in `to_sql'
[GEM_ROOT]/gems/arel-2.0.10/lib/arel/select_manager.rb:217:in `insert'

Проблема исчезнет, ​​если мы затем перезапустим производственные серверы, даже если они все еще работают со старым кодом. Таким образом, кажется, что что-то повреждается в соединении при изменении таблицы, даже если приложение, если оно не обнаружило эту ошибку, будет нормально продолжать делать то, что делало до миграции.

Я немного покопался в ActiveRecord/ARel, но самое большее, что я могу сделать, - это теоретизировать, что в какой-то момент кэшированная модель этой таблицы теряет какие-либо знания о том, какие столбцы у нее есть, но я не понимаю, почему она это делает или почему это будет происходить внезапно.

1 ответ

Решение

Я сотрудник Jon's, собираюсь ответить на это для потомков.

Эта проблема была следствием кэширования в https://github.com/rails/rails/blob/v3.0.9/activerecord/lib/active_record/base.rb; по существу, @columns и @arel_table для некоторых классов моделей были не синхронизированы, поскольку последние кэшировались во время инициализации приложения и, таким образом, наследовались от основного Unicorn любым новым работником.

Мы исправили это, предотвращая вызовы любой модели:: scoped или:: unscoped во время инициализации, где мы могли, и вызывая:: reset_column_information впоследствии, где мы не могли.

Другие вопросы по тегам