2017-02-06 7 views
0

Мы планируем использовать простой плоский стол без ссылок в качестве хранилища транзакций в Postgres. Таблица постоянно обновляется из разных потоков. Нам нужно выбрать максимум 4 минимальной 1 строки из таблицы, заблокировать ее, выполнить обновление в поле состояния и освободить блокировку. В идеале это должно быть так, что параллельные запросы не блокируют друг друга, каждый запрос может изменить свой собственный набор строк.Как обновить случайные 4 строки в таблице, используя блокировку уровня строк с помощью Postgres?

После прочтения документации я думаю, что я мог бы сделать это с:

SELECT user_id FROM rooms LIMIT 1 INTO local_user_id 
WHERE user_status=0 FOR UPDATE; 

UPDATE rooms SET user_status = 1 
WHERE user_id = local_user_id; 

Однако, мне нужно обновить 1-4 пользователей в то время, связывая весь максимум 4 пользователей в в одной транзакции сбросит количество транзакций до 1/4-го наилучшего случая (при условии, что большая часть результата выбора у 4 пользователей). Каков идиоматический способ решения этой проблемы с помощью Postgres 9.6?

Update1:

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

+0

В чем проблема с написанием 'LIMIT 4'? Это даст вам 4 или менее строк результатов. –

+0

И как я могу перебирать 4 идентификатора? – Istvan

+0

На вашем любимом языке программирования (или язык хранимых процедур, например [PL/pgSQL] (https://www.postgresql.org/docs/current/static/plpgsql.html) или [PL/Perl] (https: // www .postgresql.org/docs/current/static/plperl.html), если вы хотите написать функцию базы данных). –

ответ

1

Вы можете хранить идентификаторы в выбранном массиве:

WITH x AS (
     SELECT user_id 
     FROM rooms 
     WHERE user_status=0 
     ORDER BY random() 
     LIMIT 4 
      FOR UPDATE 
) 
SELECT array_agg(user_id) FROM x; 

И после этого обновления в одном запросе или по отдельности.

+0

Или просто замените 'select array_agg()' на 'update ... set ... где id in (выберите user_id from x)' –

+0

Если я правильно понимаю, что между блокировкой и обновлением может быть некоторое время/расчет - потому что для чего нам нужен LOCK? –

+0

Спасибо, Роман, что я пытаюсь достичь здесь: заблокировать других читателей от доступа к четырем строкам, на которых я выполняю много времени, но могу выполнять запросы, возвращающие разные ряды строк в каждый поток. Если у меня есть 16 строк, совпадающих с 4 потоками, будет обрабатываться по 4 строки каждый, параллельно и параллельно. – Istvan

 Смежные вопросы

  • Нет связанных вопросов^_^