Комментарии 13
Я продал одно место на концерт 20 раз.
А где минусы?
353мс выглядят совершенно чудовищной цифрой. Или это для последнего из 50 потоков ?
Как-то странно соотносятся мин-макс, по идее должен быть ведь гораздо больший разбег.
Причина в том, что
UPDATEв Postgres всегда берёт эксклюзивную блокировку строки на время транзакции — это встроенное поведение MVCC, а не наша логика. Конкурирующие записи в одну строку физически выстраиваются в очередь.
Что за чушь, нет в Postgres при простых обновлениях никаких блокировок строки, тупо появляются новые версии. Другое дело, что коммиты транзакций происходят последовательно, и та версия строки, которая соответствует транзакции, которая закоммичена последней, и будет видна следующим читателям. Или у вас serialized-транзакции?
Текст очевидно сгенерирован, поэтому и чушь.
век живи, век учись. Пример:
The
FOR UPDATElock mode is also acquired by anyDELETEon a row, and also by anUPDATEthat modifies the values of certain columns. Currently, the set of columns considered for theUPDATEcase are those that have a unique index on them that can be used in a foreign key (so partial indexes and expressional indexes are not considered), but this may change in the future.
https://www.postgresql.org/docs/current/explicit-locking.html
Как альтернатива для SELECT FOR UPDATE - использовать advisory locks (pg_advisory_xact_lock).
Из плюсов: для Spring Data не нужно дублировать методы findBy с @Lock, автоматически снимается в конце транзакции, не пишет в WAL (но возможно это несущественно).
Естественно, это не защищает от прямого UPDATE, поэтому нужно использовать в каждом методе сервиса, который модифицирует объект.
Ключевое отличие от предыдущих двух этапов: корректность здесь обеспечивает не Postgres, а внешний координирующий сервис. Это единственная из трёх стратегий, которая продолжит работать корректно, если приложение масштабировать на несколько инстансов за балансировщиком
Т.е. если если у меня несколько инстансов сервиса мне надо использовать redis? Господи, где ж я так согрешил то?
А ничего, что у редиса есть "сложности" с персистентностью? А если админ его вдруг перегрузит? Давайте уж тарантул ставить (кластерный? :) ) для того, чтобы разруливать блокировки в постгре.
зачем вообще проверять свободно или нет в момент обновления? это достаточно показывать пользователю где-то заранее, а так же после вставки и то, не всегда.
я когда-то давно пилил очередь через UPDATE ... RETURING этого было более чем достаточно, никаких транзакций открывать не надо, сам запрос атомарный, обновлял только одну запись, соответствующую условию, в сотни параллельных запросов без всяких накладок.


Я продал одно место на концерт 20 раз. Разбираемся, как правильно защититься от race condition в Spring Boot