У меня возникли проблемы с решением проблем параллелизма при вставке в базу данных Postgres. Модель имеет ограничение уникальности для столбца индекса, а также таблицу Postgres. Иногда два потока пытаются вставить одну и ту же запись одновременно (это неизбежно), и в этом случае оба передают проверку модели, а вторая нарушает проверку Postgres. Поэтому я поймаю исключение, и все в порядке. Это не проблема.Как я могу запросить базу данных после исключения Postgres?
Проблема заключается в том, что мой метод должен возвращать объект из базы данных, поэтому я запрашиваю db, чтобы получить запись, вставленную первым потоком (я могу смело предположить, что это то же самое, что и во втором потоке). Однако это не удается, поскольку транзакция по-прежнему находится в недопустимом состоянии из-за неудачной вставки.
Мой вопрос: Как я могу избежать второго исключения, брошенного в блок спасения, и/или включить метод для возврата записи, которая была вставлена первым потоком?
class Place
validates :index_column, uniqueness: true, allow_nil: true
def self.create_and_insert(some_params)
more_params = additional_params(some_params)
place = Place.new(some_params, more_params)
begin
place.save # Insert into place table. This initiates a transaction.
rescue ActiveRecord::RecordNotUnique => e
# Oops! Another thread beat us to it.
# The transaction is now in an invalid state.
place = Place.find_by(index_column: some_params.id) # This throws a new exception
end
place
end
end
В чем же ваше второе исключение? – archana
@archana ActiveRecord :: StatementInvalid: PG :: InFailedSqlTransaction: ERROR: текущая транзакция прерывается, команды игнорируются до конца транзакционного блока: SELECT "places". * FROM "places" WHERE "places". "Id" = 'some_id' LIMIT 1 –
@archana Так что в принципе сделка не закончилась. Я не начал транзакцию, но «save» сделал. Реализация 'after_rollback' не поможет, потому что мне нужно вернуть значение из' create_and_insert'. Могу ли я откатить его обратно из 'create_and_insert'? –