Rails postgresql, как установить уровень изоляции транзакции на сериализуемый - PullRequest
3 голосов
/ 27 октября 2011

У меня есть модель Comment, которая принадлежит_ модели топика.В модели 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.

Есть ли другой способ установить уровень изоляции транзакции?

Ответы [ 3 ]

7 голосов
/ 21 ноября 2013

Начиная с Rails 4, #transaction предоставляет опцию :isolation :

Если ваша база данных поддерживает установку уровня изоляции для транзакции, вы можете установить его следующим образом:итак:

Post.transaction(isolation: :serializable) do
  # ...
end
7 голосов
/ 27 октября 2011

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

Я действительно надеюсь, я ошибаюсь.

Одна неприятная альтернатива - изменить уровень изоляции по умолчанию для всех транзакций на сервере PostgreSQL. (Поиск http://www.postgresql.org/docs/current/static/runtime-config-client.html для "default_transaction_isolation".) Но это похоже на использование пушки, чтобы убить муху.

4 голосов
/ 07 февраля 2012

Может оказаться полезным драгоценный камень транзакции: https://github.com/qertoip/transaction_isolation

...