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

Я пытаюсь отладить проблему, которая недавно возникла в моем приложении 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 Ответ

2 голосов
/ 02 августа 2012

Я сотрудник 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, где мы не смогли.

...