Должен ли я блокировать таблицу PostgreSQL при вызове setval для последовательности с функцией максимального идентификатора? - PullRequest
1 голос
/ 19 июня 2020

У меня есть следующий SQL скрипт, который устанавливает значение последовательности, соответствующее максимальному значению столбца идентификатора:

SELECT SETVAL('mytable_id_seq', COALESCE(MAX(id), 1)) FROM mytable;

Должен ли я блокировать mytable в этом случае, чтобы предотвратить изменение идентификатора в параллельный запрос, такой как в примере ниже?

 request #1    request #2

 MAX(id)=5

              inserted id 6

 SETVAL=5

Или setval (max (id)) - это операция atomi c?

1 Ответ

0 голосов
/ 19 июня 2020

Ваше подозрение верно, этот подход зависит от условий гонки.

Но блокировка таблицы не поможет, потому что она не помешает одновременной транзакции получить новые значения последовательности. Эта транзакция будет заблокирована, пока таблица заблокирована, но с радостью продолжит вставку после снятия блокировки, используя значение последовательности, полученное во время блокировки таблицы.

Если бы можно было заблокировать последовательности, это могло бы быть решение, но невозможно заблокировать последовательности. одновременные запросы к последовательности завершатся ошибкой. Это, конечно, вызывает ошибки.

Прагматический c способ: используйте

SELECT SETVAL('mytable_id_seq', COALESCE(MAX(id), 1) + 100000) FROM mytable;

Здесь 100000 - это значение, которое безопасно больше, чем количество строк, которые может быть вставлен во время работы вашей операции.

...