Блокировка определенной строки в postgres - PullRequest
0 голосов
/ 23 июня 2018

Я достаточно новичок в Postgres, и я пытаюсь выяснить, как заблокировать определенную строку таблицы.

В качестве примера у меня есть таблица пользователей:

Name: John, Money: 1
Name: Jack, Money: 2

В своем бэкэнде я хочу выбрать Джона и убедиться, что никакие другие вызовы не могут обновить (или даже выбрать) строку Джона, пока моя транзакция не будет завершена.

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

Редактировать - Должен ли я делать это на уровне метода, например @SqlUpdate (или в какой-то другой форме - с использованием org.skife.jdbi.v2) или в самом запросе?

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

Если вы хотите заблокировать таблицу в определенной выбранной строке, вам нужно LOCK FIRST, чтобы они использовали оператор FOR UPDATE / FOR SHARE.Например, в вашем случае, если вам нужно заблокировать первую строку, вы делаете это:

BEGIN;

LOCK TABLE person IN ROW EXCLUSIVE MODE;

-- BLOCK 1

SELECT * FROM person WHERE name = 'John' and money = 1 FOR UPDATE;

-- BLOCK 2

UPDATE person set name = 'John 2' WHERE name = 'John' and money = 1;

END;

В BLOCK1 перед оператором SELECT вы ничего не делаете, только сообщая базе данных: «Эй, ябудет что-то делать в этой таблице, поэтому, когда я это сделаю, заблокируйте эту таблицу в этом режиме ".Вы можете выбрать / обновить / удалить любую строку.

Но в BLOCK2, когда вы используете FOR UPDATE, вы блокируете эту строку для других транзакций в определенных режимах (подробнее читайте doc подробности).Будет заблокирован до завершения этой транзакции.

Если вам нужен пример, выполните тест и попробуйте выполнить еще один SELECT ... FOR UPDATE в BLOCK2 до завершения первой транзакции.Он будет ожидать окончания первой транзакции и будет выбирать сразу после нее.

Только блокировка ACCESS EXCLUSIVE блокирует инструкцию SELECT (без FOR UPDATE / SHARE).

Я использую это в функции для контроля подпоследовательностей, и это здорово.Надеюсь, вам понравится.

0 голосов
/ 23 июня 2018

Как только вы обновите (а не подтвердите) строку, никакая другая транзакция не сможет обновить эту строку.

Если вы хотите заблокировать строку перед выполнением обновления (что кажется бесполезным), вы можете сделать это, используя select ... for update.

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

Даже если ваша транзакция не завершила (= зафиксировала), другие сеансы не увидят какие-либо промежуточные (несовместимые) значения - они будут видеть состояние базы данных таким, каким оно было до начала вашей транзакции. В этом весь смысл наличия реляционной базы данных, поддерживающей транзакции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...