PostgreSQL: безопасно ли использование потока генератора SELECT nextval в жестких многопользовательских средах?

Я имею в виду, как тысячи пользователей вовремя обновляют значения в базе данных?

4 ответа

Решение

Да, nextval безопасно использовать от нескольких одновременно работающих транзакций. Это его цель и причина существования.

Тем не менее, на самом деле это не "потокобезопасный" как таковой, потому что PostgreSQL использует модель многопроцессорной обработки, а не многопоточную модель, и потому что большинство клиентских драйверов (например, libpq) не допускают более одного потока одновременно. взаимодействовать с одной связью.

Вы также должны знать, что в то время как nextval гарантированно возвращает различные и растущие значения, это не гарантируется без "дыр" или "пробелов". Такие промежутки создаются, когда сгенерированное значение отбрасывается без фиксации (скажем, ROLLBACK) и когда PostgreSQL восстанавливается после сбоя сервера.

В то время как nextval всегда будет возвращать растущие числа, это не означает, что ваши транзакции будут фиксироваться в порядке, в котором они получили идентификаторы из заданной последовательности. Таким образом, вполне нормально, чтобы что-то подобное происходило:

Start IDs in table: [1 2 3 4]
1st tx gets ID 5 from nextval()
2nd tx gets ID 6 from nextval()
2nd tx commits:     [1 2 3 4 6]
1st tx commits:     [1 2 3 4 5 6]

Другими словами, дыры могут появляться и исчезать.

Обе эти аномалии являются необходимыми и неизбежными последствиями nextval Звоните, не блокируйте другого.

Если вам нужна последовательность без таких упорядочений и аномалий разрыва, вам нужно использовать конструкцию последовательности без пробелов, которая позволяет только одной транзакции за раз иметь сгенерированный незафиксированный идентификатор, эффективно устраняя весь параллелизм для вставок в эту таблицу. Это обычно реализуется с помощью SELECT FOR UPDATE или же UPDATE ... RETURNING на встречном столе.

Ищите "PostgreSQL без пробелов" для получения дополнительной информации.

Да, это потокобезопасно.

Из руководства:

NEXTVAL

Переместите объект последовательности к следующему значению и верните это значение. Это делается атомарно: даже если несколько сессий выполняются nextval одновременно, каждый из них безопасно получит отдельное значение последовательности.

(Акцент мой)

Да: http://www.postgresql.org/docs/current/static/functions-sequence.html

Это не было бы полезно в противном случае.

Изменить: Вот как вы используете nextval и currval:

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

currval возвращает последний порядковый номер, полученный этим сеансом, который используется во внешних ключах для ссылки на первую таблицу

каждый вызов nextval возвращает другое значение, не вызывайте его дважды в одном и том же наборе вставок.

И, конечно, вы должны использовать транзакции в любом многопользовательском коде.

Этот постер задал другой вопрос по тому же некорректному коду. Дело в том, что он, кажется, не знает, как работают внешние ключи, и обращает их вспять (последовательность, функционирующая как внешний ключ, является своего рода неловким ИМХО)

Кстати: это должен быть комментарий, а не ответ; но я пока не могу комментировать.

Другие вопросы по тегам