без блокировки таблицы целом при каждой вставке / обновлении, нет. То, как транзакции работают в PostgreSQL, означает, что новые строки, появляющиеся в результате одновременных транзакций, никогда не конфликтуют друг с другом; и это именно то, что будет происходить.
Вы должны убедиться, что обновления вызывают конфликт строк. В основном вам нужно реализовать нечто похожее на механику, используемую нативными последовательностями PostgreSQL.
Я бы добавил еще один столбец в таблицу, на которую ссылается ваш столбец client
, чтобы представить last_val
последовательности, которую вы будете использовать. Таким образом, каждая транзакция будет выглядеть примерно так:
BEGIN;
SET TRANSACTION SERIALIZABLE;
UPDATE clients
SET footable_last_val = footable_last_val + 1
WHERE clients.id = :client_id;
INSERT INTO footable(somecol, client_id, number)
VALUES (:somevalue,
:client_id,
(SELECT footable_last_val
FROM clients
WHERE clients.id = :client_id));
COMMIT;
Так что первое обновление таблицы клиентов завершается неудачно из-за конфликта версий до достижения вставки.