Форум программистов, компьютерный форум, киберфорум
PostgreSQL
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
1 / 1 / 1
Регистрация: 24.03.2013
Сообщений: 177

Как правильно использовать SELECT FOR UPDATE?

05.04.2023, 02:39. Показов 2524. Ответов 3

Студворк — интернет-сервис помощи студентам
Использую СУБД PGSQL.

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

SQL
1
2
SELECT MIN("CreateDate")
FROM "Document"
если минимальная дата < текущей в цикле вешается транзакция и пересчитывается поле CreateDate, достаю записи
таким запросом:

SQL
1
2
3
4
5
6
SELECT *
FROM "Document"
WHERE "CreateDate" < NOW()::DATE
ORDER BY "CreateDate"
LIMIT 10
FOR UPDATE SKIP LOCKED
Обновление записей
SQL
1
2
3
UPDATE "Document"
SET "CreateDate" = ...
...
Насколько понимаю логику работы SELECT FOR UPDATE SKIP LOCKED при параллельных вызовах
будут взяты не заблокированные записи.
Как понимаю проблема будет возникать при получении мин. значение CreateDate,
SQL
1
2
SELECT MIN("CreateDate")
FROM "Document"
заблокированные записи будут пропущены и актуальное значение не получить.
Подскажите пож-ста, можно как-то исправить эту проблему?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.04.2023, 02:39
Ответы с готовыми решениями:

Как правильно вложить подзапрос SELECT в запрос UPDATE для одной таблицы
Приветствую. Подскажите возможно ли сделать такой запрос, чтобы в одной таблице в одном столбце суммировать данные в двух строках и...

Можно ли использовать одновременно update, select, и деление?
Добрый день, есть таблица с полями width, height, ratio. width и height заполнены, ratio пустая. Могу ли я в одном запросе запросить...

Обновление базы данных на сервере. Как правильно использовать метод update() объекта SQLDataAdapter
Всем привет! Подскажите , как правильно использовать метод update() объекта SqlDataAdapter , чтобы Таблица обновлялась при удалении,...

3
55 / 50 / 5
Регистрация: 30.06.2022
Сообщений: 251
05.04.2023, 11:17
Вам придётся блокировать всю таблицу запросом вида
LOCK TABLE
Иначе в логике в дальнейшем будут возникать трудноотлавливаемые ошибки.
Или придумать что-то другое, чтобы избежать того, что вы пытаетесь сделать.

Добавлено через 3 минуты
Блокировать таблицу целиком - признак того, что в вашем подходе что-то здорово не так.
Эта блокировка больно ударит по производительности, особенно, если транзакции будут долго исполняться.
Подумайте - оно точно вам нужно?
0
1263 / 977 / 384
Регистрация: 02.09.2012
Сообщений: 3,020
05.04.2023, 21:57
FOR UPDATE выставляет блокировки на записи (row-level lock); такие блокировки не блокируют читающие запросы.
Вы просто будете видеть текущие (непересчитанные) данные в ответ на Ваш SELECT из другой транзакции,
пока не будет зафиксирована очередная пишущая транзакция с SELECT FOR UPDATE + UPDATE

Это легко показать следующим примером
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
CREATE schema test;
SET search_path = 'test';
 
CREATE TABLE document
(
    doc_id serial,
    doc_date DATE,
    doc_info text
);
 
INSERT INTO document (doc_date, doc_info)
SELECT '2023-01-01'::DATE + x, 'Document #' || x::text
FROM generate_series(1,20) AS x;
 
\q
 
-------------------------------------------------------------------------------
-- Транзакция A (открываем отдельный psql; делаем SET из стр. 5)
-- (1)
BEGIN;
 
-- (2)
SELECT * FROM document 
WHERE doc_date < '2023-01-10'::DATE
ORDER BY doc_date
LIMIT 10
FOR UPDATE skip locked;
 
-- переходим к выполнению транзакции B ...
 
-- (6)
UPDATE document SET doc_date = doc_date + 20
WHERE doc_date < '2023-01-10'::DATE;
 
-- переходим к выполнению транзакции B ...
 
-- (10)
commit;
 
-- переходим к выполнению транзакции B ...
 
-------------------------------------------------------------------------------
-- Транзакция B (открываем отдельный psql; делаем SET из стр. 5)
-- (3)(7)(11)
BEGIN;
 
-- (4)(8)(12)
SELECT MIN(doc_date) FROM document;
 
-- (5)(9)(13)
commit;
 
-- возврващемся в транзакцию A ...
Заводим данные, потом открываем два psql и выполняем шаги тразакций A и B в указанном в скобках порядке.
В результате на SELECT-ы увидите такие данные

SELECT ... FRO UPDATE выдаст это
Code
1
2
3
4
5
6
7
8
9
10
11
 doc_id |  doc_date  |  doc_info   
--------+------------+-------------
      1 | 2023-01-02 | Document #1
      2 | 2023-01-03 | Document #2
      3 | 2023-01-04 | Document #3
      4 | 2023-01-05 | Document #4
      5 | 2023-01-06 | Document #5
      6 | 2023-01-07 | Document #6
      7 | 2023-01-08 | Document #7
      8 | 2023-01-09 | Document #8
(8 строк)
SELECT MIN() выдаст это
SQL
1
2
3
4
    MIN     
------------
 2023-01-02
(1 строка)
никто никого не заблокировал, минимальная дата 2023-01-02, как и должно быть.

Далее в A выполняем UPDATE и снова пробуем транзакцию B.
Вывод такой же
Code
1
2
3
4
    min     
------------
 2023-01-02
(1 строка)
Далее в A выполняем COMMIT и снова пробуем транзакцию B.
Теперь уже новые пересчитанные данные.
Code
1
2
3
4
    min     
------------
 2023-01-02
(1 строка)
0
5 / 4 / 1
Регистрация: 10.05.2015
Сообщений: 93
06.04.2023, 12:48
Пример большего обновления пакетами по 1000 строк. Если делать обновление целиком, то в таблице создается много мертвых строк которые не успевает очищать VACUUM, в данном случае пропускаются строки, заблокированные другими транзакциями, но благодаря условию processed = false, в последующих циклах все обновится.
SQL
1
2
3
4
5
6
UPDATE vac SET processed = FALSE;
WITH batch AS (
SELECT id FROM vac WHERE NOT processed LIMIT 1000
FOR UPDATE SKIP LOCKED
)
UPDATE vac SET processed = TRUE WHERE id IN (SELECT id FROM batch);
Это пример из книги. Позволяет обновлять большие таблицы, обходя заблокированные строки.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
06.04.2023, 12:48
Помогаю со студенческими работами здесь

Как обвернуть With CTE SELECT в UPDATE FROM SELECT?
-----надо продать n штук declare @to_sale table(itemid int,qty int) insert into @to_sale select 1,35 union all select 2,36 ...

Основной функционал: Insert, Select All, Select by Id, Update, Delete
Помогите с решением задачи, не понятно как это реализовать. Создать основной функционал: Insert (Добавление) Select All (Выбрать...

Как сделать UPDATE после SELECT?
нужно записать в в соответствующий столбец дату последнего прочтения записи. естественно одним запросом будет прочитана только одна строка....

Select, delete, update, insert. как писать?
Всем привет. Как дописать delete, update, insert. Поиск по форуму не дал результатов, а черз гугл не понимаю на чужих примерах. Если...

Как сделать Update данных выбранных с помощью Select
В программе имеется DBNavigator, данные меняются, но в БД не попадают. Тип базы: Paradox. procedure TForm1.Button4Click(Sender:...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru