Перейти к содержанию

D-07 · Декомпозиция данных#

Решение двустороннее по построению. Вопрос здесь ровно «делить или держать вместе», и однонаправленного ответа у него не бывает: силы разделения взвешиваются против сил интеграции, и перевес считается, а не объявляется.

Область решения — одна сущность или одна связная группа данных, а не «данные в системе». Вторая группа — второе применение документа.

Документ собран из реестра пилота И0′. Шесть записей из семи вошли вопросами, осями и дисквалификаторами; седьмая — удаление персональных данных — вошла частным случаем первой, а не отдельной темой.


1. Что выяснить#

Вопрос Где смотреть Заполняет
О каких данных речь и кто сегодня их пишет? Схема, код, права доступа Область; сила «управление изменениями»
Сколько копий этих данных уже существует? Индексы, кэши, витрины, журналы событий, выгрузки, архивы Реестр копий — см. ниже
Какие запросы основного сценария соединяют их с данными других владельцев? Основные сценарии, медленные запросы Сила интеграции «отношения в данных»
Какие инварианты требуют атомарности между ними и соседними? Инварианты W0 Дисквалификатор
Что перестанет работать при отказе этого хранилища и сколько независимых частей это затронет? Карта зависимостей Сила «отказоустойчивость»
Есть ли среди этих данных требующие особого режима — и какого именно? Требования W0, закон, договор Сила «режим защиты», дисквалификатор
Сколько независимых потребителей держат соединения к этому хранилищу? Пулы соединений, предел хранилища Сила «управление соединениями»

Реестр копий — позвоночник решения#

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

Куда Как туда попадает Доходит ли изменение Можно ли удалить
Основное хранилище Запись — Да
Поисковый индекс ? ? ?
Кэш ? ? ?
Витрина отчётности ? ? ?
Журнал событий ? ? Часто нет
Архивная копия ? ? Часто нет

Удаление — это изменение, которое обязано дойти до всех копий. Ничего особенного в нём нет, кроме того, что невыполнение замечает юрист, а не пользователь. Отдельной темы оно не образует: если реестр копий составлен и путь изменения по нему прослежен, путь удаления прослеживается тем же способом. Механика — DATA-19: карта распространения, мягкое и жёсткое удаление, крипто-шреддинг там, где стереть нельзя.

Строка «часто нет» — не оговорка. Неизменяемая по построению копия превращает вопрос удаления в вопрос шифрования, и решать его надо до разделения, а не после.

2. Силы, дисквалификаторы и встречная половина#

Силы разделения — оси сравнения#

Шесть. Первые пять — из Ford, Richards, гл. 6, шестая пришла из разбора и в их списке отсутствует.

Сила Что записывать в ячейку
Управление изменениями Сколько независимых частей задевает изменение схемы этих данных
Отказоустойчивость Сколько частей перестанет работать при отказе хранилища
Масштабируемость Различаются ли требования к масштабу у этих данных и у соседних — и на сколько порядков
Управление соединениями Число независимых потребителей против предела хранилища
Тип хранилища Выигрывают ли эти данные от другого типа — и насколько измеримо
Режим защиты Требуют ли эти данные режима, которого не требуют соседние: шифрование на диске, аудит доступа, локализация, ограниченный круг лиц

Силы интеграции — встречная половина#

Сила интеграции — не балл, а счёт, который разделение выставляет. Как и в D-02: либо оплачена названной ценой, либо отменяет линию.

Сила Чем измеряется Оплатить можно так Когда отменяет линию
Отношения в данных Внешние ключи, соединения, представления, пересекающие линию Соединение в приложении · материализованное представление по событиям · денормализация со сверкой Целостность обеспечивается связью на уровне БД и требуется инвариантом
Транзакции Нужна ли атомарность поперёк линии — Всегда: дисквалификатор ниже
Число копий Сколько мест придётся синхронизировать после разделения Единственный источник порядка — журнал, из которого читают все Синхронизировать нечем, кроме записи в оба места: см. первый дисквалификатор

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

Дисквалификаторы#

  • Разделение порождает запись в два места без единого источника порядка. Расхождение при этом неизбежно по двум независимым причинам — гонка и частичный отказ — и не порождает ошибок, поэтому обнаруживается месяцами позже (Kleppmann). Двойная запись — не вариант с недостатками, а дефект. Либо журнал как единственный источник порядка (MSG-07), либо разделения нет.
  • Есть копия, из которой нельзя удалить, и в ней оседают данные, подлежащие стиранию. Решать надо до разделения: после — придётся переписывать архивы.
  • Разделение размазывает защищаемые данные по нескольким владельцам. Каждый попадает в периметр аудита и обязан держать режим целиком; стоимость режима умножается на число мест. Если линия проходит сквозь класс защищаемых данных — её двигают, а не оплачивают.
  • Атомарность требуется поперёк линии и следует из бизнес-инварианта. Дисквалифицирована линия, а не требование.
  • Отказ остаётся общим. Разделили логически, база физически одна — ни одна сила разделения не сработала, а сложность выросла. Проверка: сколько частей ляжет вместе с этим хранилищем после разделения.

Первые три обычно не отменяют разделение, а добавляют работу до него — и этим отличаются от последних двух, которые отменяют линию.

3. Матрица оценки#

Колонки — формы из раздела 4, применимые к этим данным. В ячейках факты с пометкой источника, не баллы.

Словарь пометок. [схема] — из схемы данных и кода · [замер] · [расчёт] · [требования] — из инвариантов и обязательств W0 · [режим] — из требований к защищаемым данным: закон, договор, внутренняя политика · [нет данных].

Пометка [нет данных] здесь редка и подозрительна. Почти всё считается по схеме, коду и конфигурации за часы. Пустая ячейка обычно означает не «не померили», а «не нашли все копии» — то есть незаполненный реестр из раздела 1.

Ось Что записывать Оставить как есть Разделить владение внутри одной базы База на сервис
Управление изменениями Сколько частей задевает изменение схемы 3 [схема] 1 — остальные через интерфейс [схема] 1 [схема]
Отказоустойчивость Сколько частей ляжет с хранилищем 3 3 — база та же 1
Масштабируемость Разница требований, в порядках Неприменимо Неприменимо Порознь
Управление соединениями Потребителей против предела 3 пула 3 пула 1 пул на базу
Тип хранилища Выигрыш от другого типа — — Возможен
Режим защиты Что обязывает класс данных и сколько мест его держит 1 место, режим целиком [режим] 1 место [режим] 2 места — режим удваивается [режим]
Сила интеграции: отношения Связи через линию и чем оплачены нет нет 4 внешних ключа → соединение в приложении [схема]
Сила интеграции: копии Сколько мест синхронизировать 2 2 4 [схема]

Нулевой вариант обязателен, и здесь он выигрывает чаще, чем в других решениях: у данных цена разделения выше, чем у кода, а обратимость ниже.

«Разделить владение внутри одной базы» — колонка, которую забывают. Отдельная схема, единственный писатель, чтение остальных через интерфейс: связность разработки падает, а физического разделения ещё нет. Промежуточная форма, и обычно правильная первая.

4. Типовые формы разделения данных#

Рынка здесь нет. Место рыночного слоя занимают формы — они не устаревают, даты съёмки у раздела нет.

Форма Что делаем Когда верна Чем оборачивается при ошибке Статус у нас
Оставить как есть Ничего Силы разделения не набрали перевеса; связи плотные Связность разработки останется — но это честная цена, а не поломка заполняется в проекте
Разделить владение внутри одной базы Схема на владельца, единственный писатель, чтение через интерфейс Первый шаг почти всегда Владение объявлено и нарушается: технически-то доступ есть
База на сервис Физическое разделение Силы разделения перевесили и соединения через линию оплачены Соединения уезжают в приложение, копий становится больше
Вынести класс данных отдельно Защищаемые или особые по типу данные — в своё хранилище Класс требует режима, которого не требуют соседние Режим удваивается, если класс вынесен не целиком
Копия только для чтения из журнала Витрина, индекс, поисковый слой Нужен другой способ доступа к тем же данным Копия становится вторым источником истины — и расходится
Разделить по времени Горячее и холодное порознь Доступ к старому редок и другой по характеру Граница «горячего» подобрана на глаз и уезжает
Разделить по арендатору или региону Данные по границе клиента или юрисдикции Локализация обязательна или радиус поражения важен (DATA-18) Кросс-арендаторские запросы становятся невозможны

Колонка «статус у нас» — те же три значения, что в рыночном слое: используем · не используем, потому что… · не рассматривали.

Формы применяются лесенкой, а не по выбору. Обычный порядок — владение внутри одной базы, потом база на сервис, потом вынос класса. Перепрыгивать можно, но тогда стоит записать, почему промежуточная ступень пропущена.

Источники раздела: Ford, Richards — Software Architecture: The Hard Parts, гл. 6 · Richardson — Database per service · Richardson — Shared database · Kleppmann — логи и почему двойная запись плоха · реестр пилота И0′

5. Эвристики#

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

Двойная запись — не компромисс, а дефект. Её не «принимают с оговоркой»: расхождение неизбежно и невидимо. Если после разделения она возникает — либо появляется журнал как источник порядка, либо линия не проводится.

Логическое разделение перед физическим. Отдельная схема и единственный писатель дают большую часть выигрыша за малую часть цены, и они обратимы. Физическое разделение — почти нет.

Защищаемые данные сначала сужают, потом делят. Чем меньше мест, где они лежат, тем дешевле режим. Линия, рассекающая класс защищаемых данных, удваивает стоимость аудита и почти никогда не окупается.

Отказ, оставшийся общим, обнуляет разделение. Самая частая полумера: сервисы разные, база одна. Проверять надо не намерение, а число частей, которые лягут вместе.

«Нет данных» здесь подозрительно. В D-01 пустая ячейка значит «не померили». Здесь — почти всегда «не нашли все копии»: всё остальное считается по схеме и коду за часы.

Согласовать с границами сервисов, но не выводить одно из другого. Данные можно разделить, оставив сервисы едиными, и наоборот. Совпадение линий — цель, а не данность; расхождение записывается как осознанная цена, а не обнаруживается через полгода.

6. Запись в ADR#

Поле ADR Чем заполняется
Контекст Данные, их писатели, реестр копий целиком и инварианты, требующие атомарности
Дисквалификаторы Какие линии отсечены и почему; отдельно — что превратилось в работу до разделения
Рассмотренные варианты Матрица раздела 3 снимком, включая нулевой вариант и обе силы интеграции
Решение Форма разделения, новый единственный писатель для каждой части, способ распространения изменений
Обоснование Какие силы перевесили и чем оплачена каждая сила интеграции
Последствия Что придётся построить: журнал или захват изменений, сверка, соединение в приложении, путь удаления по всем копиям
Условия пересмотра Раздел 7
Метод D-07 v<версия> · шаблон ADR v<версия> — рыночного снимка нет

Обязательная строка записи — реестр копий на момент решения. Он и есть «условия момента»: через год копий станет больше, и вопрос «что перепроверить» начинается именно отсюда.

7. Условия пересмотра#

  • Появилась копия, которой не было в реестре. Каждая новая копия — новое место, куда обязано доходить изменение, и повод пересчитать силу «число копий».
  • Появился инвариант, требующий атомарности поперёк линии.
  • Класс защищаемых данных изменился: то, что не требовало режима, стало требовать, или наоборот.
  • Число независимых потребителей выросло так, что упёрлось в предел по соединениям.
  • Отказ хранилища затронул больше частей, чем считалось при решении.
  • Сверка стала показывать расхождение, которого раньше не было, — значит распространение изменений сломалось, и молча.
  • Границы сервисов изменились по D-02, и линии данных разошлись с ними.

Проверка перед тем, как считать решение принятым — пять пунктов в шаблоне. Шестой, местный: реестр копий выписан целиком, и по нему прослежен путь удаления. Без этого решение принято на одной копии из семи, какой бы аккуратной ни была матрица.

Источники: Ford, Richards — Software Architecture: The Hard Parts, гл. 6 · Kleppmann — Using logs to build a solid data infrastructure · Richardson — Database per service · GitHub — разбор инцидента 21 октября 2018 · 00-workflow.md, шаг W3

История версий#

Версия Дата Изменение
1.0 2026-09-17 Первая версия. Собрана из реестра пилота И0′. 7 вопросов, 6 сил разделения, 3 силы интеграции, 5 дисквалификаторов, 7 типовых форм вместо рыночного слоя. Первый документ, построенный на двусторонней форме целиком. Удаление персональных данных вошло частным случаем согласованности, а не отдельной темой; третья сила интеграции — «число копий» — в источниках отсутствует и добавлена по разбору