Rails postgresql如何将事务隔离级别设置为可序列化

eug*_*gen 3 postgresql transactions ruby-on-rails callback

我有一个评论模型,属于一个主题模型.在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
Run Code Online (Sandbox Code Playgroud)

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

有没有其他方法来设置事务隔离级别?

Pee*_*eja 8

从Rails 4开始,#transaction提供了一个:isolation选项:

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

Post.transaction(isolation: :serializable) do
  # ...
end
Run Code Online (Sandbox Code Playgroud)


Mik*_*ll' 7

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

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
Run Code Online (Sandbox Code Playgroud)

真的希望我错了.

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

  • @eugen:使用不同的隔离级别嵌套事务是一个逻辑悖论.这是不可能做到的. (2认同)