Проведён анализ трёх связанных статей с сайта microsegment.ru, посвящённых созданию MVP гибридного хранилища (DLH), автоматизации слоя RAW и управлению жизненным циклом его партиций. Ниже представлены результаты проверки bash-кода на согласованность, выявленные ошибки и оценка соответствия современным мировым практикам в области больших данных.
🔗 Согласованность и отсутствие разногласий между статьями¶
В целом, сквозная логика наименований и структуры томов выдержана последовательно:
- Имена таблиц, схем и партиций: везде используется
TABLE_NAME="table_1", схемаraw, а партиции формируются какraw.table_1_q<N>_<YEAR>(например,raw.table_1_q2_2026). - Имена логических томов (LV): в скрипте создания
lv_raw_q<N>_<YEAR>, в скриптах архивации и восстановления —lv_raw_q<N>_<YEAR>(через переменнуюQUARTER). - Имена табличных пространств:
ts_raw_q<N>_<YEAR>в создании иts_raw_<QUARTER>в архивации/восстановлении — при передачеQUARTER="q2_2026"они совпадают. - Точки монтирования:
/mnt/raw_q<N>_<YEAR>в создании и/mnt/raw_<QUARTER>в архивации/восстановлении — также согласованы. - Группа томов: везде используется
vg_data. - Размер логического тома: в скриптах создания и восстановления фиксирован на 800G, что не противоречит друг другу.
Таким образом, сквозная согласованность идентификаторов объектов хранения (схема, таблица, партиция, LV, tablespace, mount point) соблюдена. Это позволяет скриптам создания, архивации и восстановления работать с одними и теми же сущностями без рассогласования имён.
⚠️ Выявленные ошибки и противоречия в bash-коде¶
Несмотря на общую согласованность, в скриптах присутствуют как критические логические ошибки, так и потенциально опасные конструкции.
🚨 Критическая логическая ошибка: порядок архивации и удаления табличного пространства¶
В скрипте archive_raw_partition.sh (статья о жизненном цикле партиций) нарушена последовательность операций, что может привести к потере архивируемых данных:
- Сначала выполняется
DROP TABLEдля партиции. - Затем —
DROP TABLESPACE IF EXISTSдля табличного пространства. - И только после этого том отмонтируется (
umount) и создаётся архив (tar -czf).
Однако команда DROP TABLESPACE в PostgreSQL удаляет каталог табличного пространства вместе с файлами, если том ещё смонтирован. Поскольку том отмонтируется после DROP TABLESPACE, к моменту архивации данные на томе могут быть уже удалены. В результате архив будет пустым или неполным. Корректный порядок: сначала создать архив (или как минимум отмонтировать том для сохранности), и только потом удалять табличное пространство и логический том.
🐞 Ошибка в функции логирования¶
Во всех скриптах функция log() использует команду data вместо date:
log() { echo "$(data '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" }
Это видно в статье о создании RAW (строка 30) и в статье о жизненном цикле (строки 35, 117). Команда data в стандартных дистрибутивах Linux отсутствует, поэтому временная метка в логах будет пустой или приведёт к ошибке. Это некритично для работы самих операций, но делает логирование бесполезным для аудита и отладки.
💉 Потенциальная SQL-инъекция в функции run_sql()¶
Функция run_sql() подставляет значения в SQL-запрос через sed без экранирования:
sql_command=$(echo "$sql_command" | sed "s|%I|$value|")
В комментарии указано, что это «эмуляция поведения %I» (экранирование идентификатора), но фактически подстановка идёт «как есть». Если в имени таблицы, партиции или табличного пространства появятся символы, отличные от букв, цифр и подчёркиваний (например, дефис), это может привести к синтаксической ошибке SQL или, в худшем случае, к инъекции. Для MVP с фиксированными именами риск невелик, но это не соответствует передовым практикам безопасной работы с SQL в скриптах.
🧩 Несоответствие назначения переменной REMOVE_LV¶
В скрипте create_raw.sh объявлена переменная REMOVE_LV=$1, но далее она нигде не используется. Вероятно, это остаток от логики удаления, скопированный из другого скрипта. Это не влияет на работу, но свидетельствует о неполной вычитке кода.
🔁 Жёсткая привязка к кварталам и году¶
Скрипт create_raw.sh содержит цикл for i in {2..4}, то есть создаёт партиции только для 2, 3 и 4 кварталов указанного года (YEAR="2026"). Первый квартал не создаётся. Это согласуется с примером в статье, но делает скрипт негибким: для создания Q1 потребуется ручное вмешательство. В мировой практике автоматизация создания партиций должна быть параметризованной (например, через pg_partman или оркестратор), а не жёстко зашитой в bash-цикл.
🛑 Игнорирование ошибок при создании PV/VG¶
В create_raw.sh при создании физического тома и группы томов используется конструкция if ! sudo pvcreate ...; then log ... fi без последующего exit 1. Это означает, что ошибка создания PV или VG не остановит скрипт, и он продолжит выполнение, что может привести к неконсистентному состоянию (например, попытке создать LV в несуществующей VG). Учитывая, что в начале скрипта стоит set -e, логичнее было бы использовать простой вызов без if !, чтобы ошибка прерывала выполнение.
🌍 Соответствие мировым трендам в области хранения больших данных (2026)¶
Предложенное решение — это классический реляционный подход к организации RAW-слоя на PostgreSQL с ручным управлением LVM и bash-скриптами. С точки зрения современных трендов 2026 года, он имеет как сильные стороны (простота, работа в закрытом контуре, использование знакомых технологий), так и существенные расхождения с мейнстримом.
✅ Что соответствует трендам¶
- Слоистая архитектура (медальон): схема
STG → RAW → ODS → DDS → CDMсоответствует общепринятой медальон-архитектуре (Bronze → Silver → Gold), которая остаётся базовым паттерном организации lakehouse. - Разделение хранения и вычислений (частично): вынесение партиций на отдельные LVM-тома можно рассматривать как попытку изоляции горячих и холодных данных, что перекликается с идеей tiered storage, хотя реализовано на уровне ОС, а не объектного хранилища.
- Управление жизненным циклом: наличие скриптов архивации и восстановления партиций демонстрирует осознанный подход к retention, что является обязательной практикой для RAW-слоя.
❌ Ключевые расхождения с мировыми практиками¶
-
Отсутствие открытого табличного формата. В 2026 году де-факто стандартом для lakehouse стали Apache Iceberg, Delta Lake и Apache Hudi; Iceberg доминирует в транзакционных нагрузках и становится «языком» хранения данных. Решение на PostgreSQL с партиционированными таблицами не обеспечивает ACID на уровне озера, time travel, эволюцию схемы и скрытое партиционирование, которые являются ключевыми преимуществами современных lakehouse. Это скорее «data warehouse на PostgreSQL», чем полноценный lakehouse.
-
Физическое управление партициями вместо метаданных. В современных lakehouse жизненный цикл партиций управляется через метаданные (snapshot expiration, retention policies), а не через
DROP TABLEиDROP TABLESPACE. Iceberg, например, позволяет менять стратегию партиционирования без перезаписи данных. В предложенном решении архивация и восстановление требуют ручного управления LVM,tar.gzи прав доступа, что плохо масштабируется и не автоматизируется декларативно. -
Использование bash и LVM вместо декларативных инструментов. Мировые практики 2026 года предполагают использование оркестраторов (Airflow, Dagster), декларативных фреймворков (dbt, SQLMesh) и инфраструктуры как кода (Terraform, Ansible). Bash-скрипты с
sedиtee -a /etc/fstab— это императивный подход, который трудно тестировать, версионировать и поддерживать. Для MVP в закрытом контуре это допустимо, но при промышленном внедрении станет узким местом. -
Ориентация на локальные диски, а не на объектное хранилище. Современные lakehouse строятся поверх объектных хранилищ (S3, ADLS, GCS) с разделением вычислений и хранения. Предложенное решение жёстко привязано к LVM и локальным файловым системам (
xfs), что ограничивает эластичность и возможности горизонтального масштабирования. -
Отсутствие каталога и управления метаданными. В экосистеме lakehouse важную роль играют каталоги (REST-каталог Iceberg, Unity Catalog, Nessie), обеспечивающие версионирование, изоляцию и управление доступом. В решении на PostgreSQL эту роль частично выполняет системный каталог PostgreSQL, но он не предназначен для управления жизненным циклом данных в lakehouse-парадигме.
💎 Выводы и рекомендации¶
Предложенный набор скриптов демонстрирует работающий MVP для закрытого контура, и с точки зрения внутренней согласованности имён он последователен. Однако в коде есть критическая ошибка порядка операций при архивации (риск потери данных), а также ряд некритичных, но нежелательных дефектов (опечатка data, потенциальная SQL-инъекция, жёсткая привязка к кварталам).
С точки зрения мировых трендов 2026 года решение является консервативным и не соответствует мейнстримной архитектуре lakehouse. Оно может быть оправдано для быстрого старта в изолированной среде без доступа к объектным хранилищам, но при развитии проекта потребует перехода на открытые табличные форматы (Iceberg/Delta Lake) и декларативные инструменты управления жизненным циклом данных.
Рекомендации по доработке:
- Исправить порядок в
archive_raw_partition.sh: создавать архив доDROP TABLESPACE(или как минимум доDROP TABLE). - Заменить
dataнаdateво всех функцияхlog(). - Добавить проверку существования VG перед
vgcreateи прерывать выполнение при ошибках создания PV/VG. - Для промышленного использования рассмотреть переход на Apache Iceberg с каталогом (например, REST-каталог) и оркестрацию через Airflow, что обеспечит соответствие актуальным практикам Data Lakehouse.

