Выберите для поведения обновления

Я хорошо понимаю, что происходит с обновлением строки, когда используется SELECT FOR UPDATE и выполняется другой SELECT/UPDATE. Но что происходит, когда выполняются два запроса с помощью SELECT FOR UPDATE.

Например:

  1. Поток A запускает транзакцию, выполняет SELECT FOR UPDATE для строки, получает некоторую информацию и начинает HTTP-запрос, который требует времени. После возврата вызова транзакция фиксируется, а сеанс закрывается.
  2. Поток B, пока A ожидает запроса, запускает новую транзакцию и выполняет SELECT FOR UPDATE для той же строки. Будет ли он извлекать информацию и выполнять HTTP-запрос или будет ждать, пока поток A зафиксирует/выполнит обновление, а затем извлечет данные из строки.

Меня не волнует, что будет после того, как запрос вернется и придет время обновить таблицу. Второй, который идет на обновление, либо выбросит, либо обновит последние возможные данные в строке.

Но будет ли фактический HTTP-запрос выполняться ими обоими? Другими словами, может ли в этом сценарии SELECT FOR UPDATE использоваться (злоупотреблять) в качестве механизма синхронизации потоков?


person idipous    schedule 21.04.2015    source источник


Ответы (1)


Вы смешиваете слои. PostgreSQL не поддерживает HTTP. SELECT ... FOR UPDATE не имеет ничего общего с HTTP.

Вот как это работает:

  • Сессия 1 делает BEGIN
  • Сессия 2 делает BEGIN
  • Сеанс 1 выполняет SELECT ... FOR UPDATE и получает одну или несколько строк
  • Сеанс 2 выполняет SELECT ... FOR UPDATE и сопоставляет одну из тех же строк, поэтому он блокируется, ничего не возвращая, пока...
  • Сессия 1 выполняет COMMIT или ROLLBACK
  • Сеанс 2 получает результаты предыдущего SELECT ... FOR UPDATE

Другими словами, продолжительность блокировки контролируется границами транзакций. Где лежат границы транзакций, зависит от вашего приложения и фреймворка, находящегося выше уровня базы данных, который вы никак не идентифицировали.

(Кроме того, это не имеет ничего общего с потоками).

person Craig Ringer    schedule 21.04.2015
comment
Спасибо, Крейг. Да, я знаю, что потоки и Http не имеют отношения к PostgreSQL. Может я не правильно выразился. Тем не менее, вы ответили на мой вопрос, я думаю. Сеанс 2 блокирует его выполнение и не продолжается до тех пор, пока сеанс 1 не зафиксирует. Таким образом, он не перейдет к вызову HTTP, который существует после SELECT FOR UPDATE, пока сеанс 1 не зафиксирует изменения. Я прав? - person idipous; 21.04.2015
comment
@idipous Как я уже сказал, на это невозможно ответить, потому что я не знаю, какую структуру вы используете, как она управляет транзакциями и т. д. Это зависит от того, когда приложение фиксируется. Это все. Поэтому вам нужно выяснить, когда приложение будет зафиксировано. Судя по вашим изменениям, транзакция остается открытой на протяжении всего HTTP-обмена с клиентом, и в этом случае да, это предотвратит продолжение сеанса B до тех пор, пока сеанс A не вернется. Все зависит от того, когда вы делаете коммит. - person Craig Ringer; 21.04.2015
comment
Я отредактировал свой вопрос, чтобы прояснить начало транзакции и точки фиксации. - person idipous; 21.04.2015