Как стать автором
Обновить

Комментарии 8

Спасибо за интересную статью!

Я правильно вас понял, что вы выстроили в очередь создание логически зависимых объектов?

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

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

В принципе ясно. Но остаётся не понятным взаимодействие потоков. Создание объектов происходит в разных потоках, каждый из которых запрашивает правильно выстроенную последовательность? Или же созданием занимается один поток?

Как я понял, у вас несколько клиентов создают таблицы и индексы. Под клиентом я понимаю поток. Кто из них при этом вьюху зовёт?

Если каждый поток получает из вью свою собственную цепочку, то разве оно не было так и раньше? Ведь вроде бы каждый поток создаёт только ему нужные объекты. Но ваше решение явно заставляет весь процесс выполняться шаз за шагом. Только за счет чего это происходит?

Головной процесс создает секционированные таблицы с индексами и составляет перечень параллельных исполнителей (являясь координатором), используя при составлении необходимые условия распределения (только головной процесс читает представление). Каждый исполнитель получает задание на отработку некой цепочки таблиц (в идеальном случае, только одной таблицы, несвязанной ни с какими другими) - при отработке генерируются секции (именно этот процесс представляется длительным и ресурсозатратным и, поэтому, подвергаемым распараллеливанию (например, можно в отдельном потоке создать отдельную таблицу со структурой, аналогичной структуре секционированной таблицы, наполнить ее, и только в конце присоединить ее к головной таблице)). Исполнители ни с кем не взаимодействуют - они пассивны. Но это так в приведенном тестовом примере - конечная реализация может быть разной.

Вернее, головной процесс читает представление для распределения, а каждый дочерний - для получения своей цепочки.

Первоначально, распараллеливание - стопроцентное. А в итоге, с использованием нового условия, мы, вынужденно, проблемные пары/тройки и т.д. таблиц объединяем в составные цепочки, для безопасного исполнения, уменьшая т.о. уровень распараллеливания.

Ага. Понял. Т.е. раньше разные потоки генерировали секции и индексы для одной и той же таблицы? В общем, тогда понятно откуда грабли. DDL же ж у нас транзакционный. Вот и выходило, что одна транзакция не видела, что имя секции уже захвачено, но еще не закомичено, т.е. что такое имя уже есть ей было не ведомо. Полагаю проблема в этом была

Нет-нет - как раз, самое интересное в рассмотренном кейсе то, что каждый из параллельных потоков занимается созданием своей секции - и секции разные и головная таблица тоже - изначально, мы сразу обозначаем, что с нашей стороны логика правильная - мы не делаем попытки создать одно и то же в конфликтном режиме - для пар/троек и т.д. таблиц со сходными именами получается так, что, из-за ограничения на длину системного имени, "вторая по времени исполнения" транзакция не видит то, что ее "скомпонованное путем урезания" имя для индекса уже занято "первой" транзакцией - возникает конфликт, но это не ошибка Postgres - нужно "разрулить" такие инструкции со стороны пользователя (пользователя СУБД).

Зарегистрируйтесь на Хабре, чтобы оставить комментарий