【问题标题】:Rails postgresql how to set transaction isolation level to serializableRails postgresql如何将事务隔离级别设置为可序列化
【发布时间】:2011-10-27 11:27:10
【问题描述】:

我有一个 Comment 模型,它属于 Topic 模型。在 Comment 模型上,我有一个 before_create 回调

def on_create
  Topic.transaction(:require_new => true) do
    Topic.connection.execute('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE')
    self.topic.increment!(:comment_counter) if conditions
  end
end

问题是我得到了ActiveRecord::StatementInvalid: PGError: ERROR: SET TRANSACTION ISOLATION LEVEL must be called before any query

还有其他方法可以设置事务隔离级别吗?

【问题讨论】:

  • 可以在开始交易前设置吗?
  • 这实际上是我的问题 - 如何在整个模型保存事务开始之前设置隔离级别。

标签: ruby-on-rails postgresql transactions callback


【解决方案1】:

从 Rails 4 开始,#transaction provides an :isolation option:

如果你的数据库支持为事务设置隔离级别,你可以这样设置:

Post.transaction(isolation: :serializable) do
  # ...
end

【讨论】:

    【解决方案2】:

    PostgreSQL 要求在事务开始之后和任何 DML(SELECT、INSERT、DELETE 等)语句之前执行 SET TRANSACTION 语句。从文档看来,所有这些东西都必须通过连接对象完成,而不是事务对象。类似(未经测试)

    Topic.connection.begin_db_transaction
      Topic.connection.execute('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE')
      # Other things go here. I'd test with another literal SQL statement to make
      # sure it works like I'd hope it does. Then possibly try rewriting in Rails.
    Topic.connection.commit_db_transaction
    

    真的希望我错了。

    一个令人讨厌的替代方法是更改​​ PostgreSQL 服务器上所有事务的默认隔离级别。 (在http://www.postgresql.org/docs/current/static/runtime-config-client.html 搜索“default_transaction_isolation”。)但这感觉就像用大炮杀死苍蝇。

    【讨论】:

    • 代码可以独立工作,但主要问题是这个Topic事务被包装在另一个事务中。显然,不可能使用具有不同隔离级别的嵌套事务,因此我需要一种方法来使第一个事务可序列化 - 我不想让 Comment 模型上的任何事务可序列化。
    • @eugen:嵌套具有不同隔离级别的事务是一个逻辑悖论。这是做不到的。
    • @Catcall,谢谢 - 您的 cmets 实际上为我指出了解决问题的另一种方法,我将按原样接受答案。
    • @Catcall:通过使用 after_commit 回调 - 这个回调在原始事务提交后运行,因此它可以在自己的事务中运行。
    • @Catcall:这是一种解决方案。我不确定它是不是最好的,但它现在有效。
    【解决方案3】:

    您可能会发现 transaction_isolation gem 很有帮助:https://github.com/qertoip/transaction_isolation

    【讨论】:

      猜你喜欢
      • 2011-03-31
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 2021-12-06
      • 2013-11-20
      • 1970-01-01
      • 2011-07-19
      • 1970-01-01
      相关资源
      最近更新 更多