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

我有一个评论模型,属于一个主题模型。 在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

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

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”。)但感觉就像使用大炮杀死苍蝇一样。

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

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

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

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