迁移表和after_create挂接时,PreparedStatement缓存失效

时间:2017-11-30 14:36:35

标签: ruby-on-rails-4

迁移表时,RoR 4中存在一个错误:如果您对此表执行了一个已执行且位于预准备语句缓存中的查询,则会出现错误。

要解决此问题而不必升级到RoR 5,我们决定按照here所述修补ActiveRecord#transaction方法。

基本上代码如下:

module TransactionRecoverable
  module ClassMethods
    raise "We may no longer need the monkeypatch #{__FILE__}!" if Rails::VERSION::MAJOR > 4

    def transaction(*args)
      begin
        super(*args) do
          yield
        end
      rescue PG::InFailedSqlTransaction => e
        # Raise error to parent transaction if in child transaction.  This prevents issues with dependency errors in a case where you have a transaction that spawns two child transactions, the second depending on the result of the first.  This happens because the rollback_db_transaction rolls back everything under the parent transaction NOT the current transaction.
        raise e if connection.open_transactions > 0

        connection.rollback_db_transaction
        connection.clear_cache!

        super(*args) do
          yield
        end
      end
    end
  end
end

class << ActiveRecord::Base
  prepend TransactionRecoverable::ClassMethods
end

它的作用是当发生这样的错误时,它会触发DB中当前事务的ROLLBACK,然后清除准备好的语句缓存。然后它重新执行查询,使用新的表结构为此查询重新构建准备好的语句缓存。

我们现在面临的问题是,如果在after_create挂钩期间发生错误,则会触发ROLLBACK并取消完整的数据库事务(create和{{1 SQL语句)。

但不幸的是,唯一重试的是after_create钩子中的代码(以及SQL)。所以基本上没有崩溃,但我的对象根本没有创建...

目前我通过用after_create挂钩替换after_create挂钩来修复它,但这不是很令人满意。

知道如何解决这个问题吗?

0 个答案:

没有答案