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 возвращает другое значение, не вызывайте его дважды в одном и том же наборе вставок.
И, конечно, вы должны использовать транзакции в любом многопользовательском коде.
Этот постер задал другой вопрос по тому же некорректному коду. Дело в том, что он, кажется, не знает, как работают внешние ключи, и обращает их вспять (последовательность, функционирующая как внешний ключ, является своего рода неловким ИМХО)
Кстати: это должен быть комментарий, а не ответ; но я пока не могу комментировать.