Нет, документация неверна. Использование только транзакции не избегайте этой проблемы. Это гарантирует только откат всей транзакции, если произойдет исключение - чтобы в базе данных не сохранялось несогласованное состояние.
К избегать этой проблемы вы должны заблокировать таблицу - внутри транзакции, поскольку все блокировки освобождаются в конце транзакции. Что-то вроде:
BEGIN;
LOCK TABLE mytbl IN SHARE MODE;
-- do your find_or_create here
COMMIT;
Но это не волшебное лекарство от всего. Это может стать проблемой производительности, и может быть deadlocks (параллельные транзакции взаимно пытаются заблокировать ресурсы, которые другой заблокировал уже). PostgreSQL обнаружит такое условие и отменит все, кроме одной из конкурирующих транзакций. Вы должны быть готовы повторить операцию при сбое.
The PostgreSQL manual about locks.
Если у вас нет много параллелизма вы также можете просто игнорировать эту проблему. Временной интервал очень крошечный, поэтому на самом деле это происходит очень редко. Если вы поймаете ошибку дублирования ключевого нарушения, которая не принесет вреда, вы тоже это рассмотрели.
Другие полезные страницы. Документы: http://www.postgresql.org/docs/current/interactive/mvcc.html PostgreSQL версии 9.1 или более поздней сериализуемой реализации: http://wiki.postgresql.org/wiki/SSI Другие уровни изоляции или версии PostgreSQL: http : //www.postgresql.org/files/developer/concurrency.pdf – kgrittn
Но каков правильный способ поймать «ошибку дублирования ключевого нарушения» в DBIC? –
@eugeney: Я полагаю, вы открываете для этого новый вопрос, а не комментарий. Вы всегда можете ссылаться на этот, чтобы сохранить себе некоторую типизацию. –