powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Блокировки при вставке в таблицу
12 сообщений из 12, страница 1 из 1
Блокировки при вставке в таблицу
    #39741707
bff7755a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть задача пересоздать таблицу с 1 млрд строк с минимальным простоем. Я придумал навесить на старую таблицу триггер, который будет обновлять или добавлять данные в новой таблице при изменении данных в старой и после этого пакетно копировать данные из старой таблицы в новую. В таблице есть индексированное поле created_at (дата вставки записи) и я решил использовать его для разбиения строк на пакеты и копировать данные по одному дню. Для того, чтобы процесс можно было распараллелить я создал табличку, в которую записывается дата, данные за которую сейчас переносятся. На момент вставки в эту таблицу берётся advisory lock и освобождается сразу же после вставки. Заодно логируется некоторая элементарная статистика. Процедура выглядит следующим образом:

Код: plsql
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.
create or replace
function public.packages_catchup() returns integer as $$
declare
    vResult integer; vCurrentDate date;
    vAdvisoryLockID integer := 1984;
    vMinDate date := '2017-07-18'; /* select min(created_at) from packages; */
begin
    /* In order to hold lock as less as possible we
       use advisory locks instead of common locks, because
       command locks are always held until end of transaction */
    perform pg_advisory_lock(vAdvisoryLockID);

    select coalesce(max(day) + interval '1 day', vMinDate)
      from public.package_catchup_log
      into vCurrentDate;

    insert into public.package_catchup_log (day)
    values (vCurrentDate);

    perform pg_advisory_unlock(vAdvisoryLockID);

    insert into public.packages_new
    select * from public.packages p
    where created_at >= vCurrentDate and
          created_at < vCurrentDate + interval '1 day' and
          not exists (
            select *
              from public.packages_new pn
             where pn.id = p.id and
                   created_at >= vCurrentDate and
                   created_at < vCurrentDate + interval '1 day'
          );

    get diagnostics vResult := ROW_COUNT;

    raise warning 'public.packages_catchup(): % rows have been moved', vResult;

    update public.package_catchup_log
       set rows_count = vResult,
           dt_end = clock_timestamp()
     where day = vCurrentDate;

    return vResult;
end;
$$ language plpgsql;



Проблема в том, что если запустить процедуру в двух параллельных транзакциях, одна из транзакций начинает висеть в ожидании, пока не закончится первая. И судя по pg_locks проблема не в advisory locks. Я не понимаю, откуда вообще берётся блокировка при вставке. Может, знающие умы что-нибудь дельное посоветуют? Где и что я упустил?
...
Рейтинг: 0 / 0
Блокировки при вставке в таблицу
    #39741711
bff7755a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Судя по логам, блокировка возникает при вставке в индекс, навешенный на новую таблицу.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
(42498) 2018-12-02 13:45:07 UTC [15447] STATEMENT:  /*NO LOAD BALANCE*/ SELECT now(), public.packages_catchup();
(42496) 2018-12-02 13:45:07 UTC [15446] LOG:  duration: 109388.232 ms  statement: /*NO LOAD BALANCE*/ SELECT now(), public.packages_catchup();
(48792) 2018-12-02 13:45:33 UTC [16494] LOG:  process 16494 still waiting for ShareLock on transaction 996384294 after 1000.083 ms
(48792) 2018-12-02 13:45:33 UTC [16494] DETAIL:  Process holding the lock: 16493. Wait queue: 16494.
(48792) 2018-12-02 13:45:33 UTC [16494] CONTEXT:  while inserting index tuple (5860744,4) in relation "packages_new_pkey"
	SQL statement "insert into public.packages_new
	    select * from public.packages p
	    where created_at >= vCurrentDate and
	          created_at < vCurrentDate + interval '1 day' and
	          not exists (
	            select *
	              from public.packages_new pn
	             where pn.id = p.id and
	                   created_at >= vCurrentDate and
	                   created_at < vCurrentDate + interval '1 day'
	          )"
	PL/pgSQL function packages_catchup() line 21 at SQL statement
...
Рейтинг: 0 / 0
Блокировки при вставке в таблицу
    #39741714
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bff7755aЕсть задача пересоздать таблицу с 1 млрд строк с минимальным простоем.
А какая задача изначальная? Может, банальный pg_repack?

bff7755aЯ не понимаю, откуда вообще берётся блокировка при вставке
Уникальные индексы есть?
...
Рейтинг: 0 / 0
Блокировки при вставке в таблицу
    #39741716
bff7755a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MelkijА какая задача изначальная? Может, банальный pg_repack?

Изначально вакуум работает по таблице очень долго (больше недели), было установлено, что в версиях 9.5.* до 9.5.15 есть баг, когда вакуум работает бесконечно если на таблице есть битые индексы, но обновление до 9.5.15 не помогло, поэтому решили перенести таблицу, так как xid не бесконечный и до wraparound осталось около 1 млрд транзакций.

bff7755aЯ не понимаю, откуда вообще берётся блокировка при вставке
Уникальные индексы есть?[/quot]
Есть, PK по id. Это поле типа uuid (к сожалению).
...
Рейтинг: 0 / 0
Блокировки при вставке в таблицу
    #39741721
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bff7755a,

ну вот pg_repack и воспользуйтесь.
...
Рейтинг: 0 / 0
Блокировки при вставке в таблицу
    #39741723
bff7755a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Melkijbff7755a,ну вот pg_repack и воспользуйтесь.
У меня есть подозрения, что с таблицей (или индексами на ней) что-то не то. Стороннее расширение тоже не факт что с этим справится, поэтому выбрали гарантированный вариант. А вопрос всё-таки был про блокировки.
...
Рейтинг: 0 / 0
Блокировки при вставке в таблицу
    #39741724
bff7755a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
И, кстати, pg_repack замораживает строки? Иначе в моём случае он будет бесполезен.
...
Рейтинг: 0 / 0
Блокировки при вставке в таблицу
    #39741729
bff7755a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
bff7755aИ, кстати, pg_repack замораживает строки? Иначе в моём случае он будет бесполезен.
Прочитал документацию. Он пересоздаёт таблицу на самом деле, так что всё OK. Можно попробовать.
...
Рейтинг: 0 / 0
Блокировки при вставке в таблицу
    #39741733
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bff7755a,

pg_repack делает копию таблицы через insert select, строит индексы, нагоняет diff который записал триггером, затем подменяет relfilenode и прочие зависимости, relfrozenxid тоже обновляет. Потому что все данные были скопированы только что.
И это сильно быстрее и надёжнее, чем вы сейчас будете отлаживать в спехе аналогичный велосипед.

bff7755aА вопрос всё-таки был про блокировки.
Так на уникальных индексах и стоите вероятно. Где-нибудь из package_catchup_log
...
Рейтинг: 0 / 0
Блокировки при вставке в таблицу
    #39741735
bff7755a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Melkij, есть только одна проблема. Уже работает prevent wraparound vacuum. А с ним у pg_repack похоже бывают некотрые конфликты ( https://github.com/reorg/pg_repack/issues/148).
...
Рейтинг: 0 / 0
Блокировки при вставке в таблицу
    #39741736
Melkij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bff7755a,

create index concurrently pg_repack делает если запросили пересборку только индексов --only-indexes
В этом случае логика работы в принципе по другому пути идёт и сама таблица никак не затрагивается.
...
Рейтинг: 0 / 0
Блокировки при вставке в таблицу
    #39745133
bff7755a
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Melkij, спасибо за совет. pg_repack мне помог. Отработал на базе с 3000 TPS, блокировки были только в начале и в самом конце, когда он переключал таблицы.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Блокировки при вставке в таблицу
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]