LINUX.ORG.RU

Логика работы SELECT FOR UPDATE

 ,


0

2

Использую СУБД PGSQL.

Нужно получить мин. значение CreateDate из таблицы документ

SELECT MIN("CreateDate")
FROM "Document"

если минимальная дата < текущей в цикле вешается транзация и пересчитывается поле CreateDate, достаю записи таким запросом:

SELECT *
FROM "Document"
WHERE "CreateDate" < NOW()::DATE
ORDER BY "CreateDate"
LIMIT 10
FOR UPDATE SKIP LOCKED
Обновление записей
UPDATE "Document"
SET "CreateDate" = ...
...

Насколько понимаю логику работы SELECT FOR UPDATE SKIP LOCKED при паральленых вызовах будут взяты не заблокированные записи. Как понимаю проблема будет возникать при получении мин. значение CreateDate,

SELECT MIN("CreateDate")
FROM "Document"
 
заблокированные записи будут пропущены и актульное значение не получить. Подскажите пож-ста можно как-то исправить эту проблему?

Не хочется влезать во флуд и холивар, но у тебя явно всё очень плохо с моделью данных. За исключением очень-очень редких случаев, select for update (и уж тем более множественный) это признак ошибки в проектировании. Да и вообще сам оператор update часто намекает на достаточно высокую вероятность проблемы в схеме БД.

no-dashi-v2 ★★
()

Не совсем ясна задача.

Есть ощущение что возможно вам нужно завернуть всё это дело в функцию и применять pg_try_advisory_xact_lock() внутри неё.

Toxo2 ★★★
()

Без понимания, что именно надо сделать в конечном итоге ничего сказать нельзя.

Ты описал пример неправильного подхода, а что считать правильным -неясно.

Psilocybe ★★★★
()
Последнее исправление: Psilocybe (всего исправлений: 1)
Ответ на: комментарий от maxcom

Select без for update не блокируется

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

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

Toxo2 ★★★
()

Нафига тебе двигать дату создания документа - не понятно. Она не должна двигаться по идее, ну да ладно.

если минимальная дата < текущей

Но она всегда будет меньше текущей, т.е. в прошлом.

цикле вешается транзация и пересчитывается поле

Ты зачем-то пытаешься делать императивно то, что императивно делать не надо.

Обновление записей

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

crutch_master ★★★★★
()
Ответ на: комментарий от Anoxemian

Если я правильно понял описанную логику, он сначала проверяет есть ли записи с датой меньше текущей в принципе(и для этого вычисляет min()) сравнивает в приложении полученную дату с текущей и потом уже выбирает циклом по 10 записей и апдейтит их. Во всем этом непонятно для чего ему эта проверка значения min() в приложении(а если приложение и база на разных хостах, то там еще и разное текущее время может быть)? Ведь можно сразу с ходу делать select for update

cobold ★★★★★
()