Прямой ответ
Сверка после миграции подтверждает, что данные перенесены корректно. Совпадение числа строк — необходимое, но недостаточное условие: строки могут присутствовать с неверными значениями.
Четыре уровня проверки, от дешёвых к дорогим:
| Уровень | Что проверяет | Стоимость |
|---|---|---|
| Количество строк | Потерю строк | Низкая |
| Агрегаты по колонкам | Систематическую ошибку преобразования | Низкая |
| Контрольные суммы по диапазонам | Расхождение в конкретной части | Средняя |
| Выборочное сравнение строк | Ошибку в отдельных значениях | Высокая |
Количество строк выявляет потерю:
SELECT
(SELECT count(*) FROM old_orders) AS old_count,
(SELECT count(*) FROM new_orders) AS new_count;
Агрегаты по колонкам выявляют систематическую ошибку. Если сумма значений совпадает, а число строк тоже, вероятность массовой ошибки преобразования мала:
SELECT sum(total), count(DISTINCT customer_id), min(created_at), max(created_at)
FROM old_orders;
Контрольные суммы по диапазонам локализуют расхождение. Сравнение выполняется по сегментам идентификаторов, поэтому несовпадение указывает на конкретный диапазон:
SELECT id / 100000 AS segment,
count(*) AS cnt,
md5(string_agg(id::text || ':' || status, ',' ORDER BY id)) AS checksum
FROM orders
GROUP BY 1
ORDER BY 1;
Сравнение результатов по обоим хранилищам показывает сегменты с расхождением, и проверка сужается до них; о контрольных суммах — в статье про проверку целостности.
Выборочное сравнение строк проверяет конкретные значения. Выборка формируется случайно и по граничным случаям: минимальные и максимальные значения, пустые значения, строки с нестандартными символами.
Отдельная категория — проверка бизнес-правил. Данные могут быть перенесены побайтово верно, но нарушать ограничения новой модели:
-- заказы без позиции не должны существовать
SELECT count(*) FROM new_orders o
WHERE NOT EXISTS (SELECT 1 FROM order_items i WHERE i.order_id = o.id);
Такие проверки специфичны для предметной области и не заменяются сравнением сумм.
При двойной записи сверка выполняется непрерывно, а не однократно, поскольку расхождения возникают во время работы; о механизме — в статье про двойную запись.
Что сверка не обнаруживает
Сверка подтверждает соответствие перенесённых данных исходным, но четыре класса проблем остаются вне её покрытия.
Отсутствие данных в источнике. Если запись не существовала до переноса, сверка не может выявить её отсутствие. Обнаружение требует отдельной проверки бизнес-правил либо жалобы пользователя.
Семантическая корректность значения. Сверка подтверждает совпадение значения между структурами, но не его правильность. Ошибочное значение, перенесённое без изменения, совпадает в обеих структурах.
Производные и кэшированные данные. Значения, вычисляемые из перенесённых данных, обновляются отдельно и не входят в сверку. Устаревший кэш после переноса обнаруживается по расхождению с вычисленным значением.
Данные во внешних системах. Копии у партнёров, выгрузки и реплики вне контура переноса не сверяются и могут оставаться устаревшими.
Практическое следствие: сверка — необходимое, но не достаточное условие корректности. Дополнение — выборочная проверка бизнес-правил на перенесённых данных и проверка производных значений.
Отдельно стоит фиксировать, какие проверки выполнены, а какие нет. Перечень выполненных проверок позволяет при последующей проблеме определить, была ли она в зоне покрытия сверки либо вне её.
Практика: организация сверки
1. Начинайте с дешёвых проверок. Количество и агрегаты выполняются быстро и отсеивают грубые ошибки до детальной сверки.
2. Сравнивайте по сегментам, а не целиком. Одно несовпадение по всей таблице не показывает, где именно расхождение.
3. Проверяйте граничные случаи. Пустые значения, даты вне ожидаемого диапазона и строки с нестандартными символами — источник ошибок преобразования.
4. Валидируйте бизнес-правила. Ограничения новой модели проверяются отдельными запросами; о процессе — в статье про миграцию данных.
5. Автоматизируйте сверку по расписанию. Ручная проверка выполняется один раз и пропускает расхождения, возникшие позже.
6. Фиксируйте расхождения списком. Перечень несовпавших строк нужен для устранения, а не только число расхождений.
7. Учитывайте изменяющиеся данные. При работающем сервисе значения меняются, поэтому сверка сравнивает состояние на определённый момент либо допускает расхождение по свежим записям.
8. Документируйте ожидаемые расхождения. Часть строк может не переноситься намеренно, и это фиксируется в плане.
Рекомендации:
- Не ограничивайтесь числом строк. Совпадение количества при неверных значениях — типичный пропущенный случай.
- Сверяйте до переключения чтения. После переключения расхождение влияет на пользователей.
- Проверяйте направление расхождения. Данные могут присутствовать в новом хранилище и отсутствовать в старом, и наоборот.
- Учитывайте порядок в контрольной сумме. Агрегирование без упорядочивания даёт нестабильный результат.
- Сохраняйте результат сверки. Дата, объём и число расхождений фиксируются для подтверждения корректности.
Практический сценарий: пропущенная ошибка преобразования при совпадении количества
Контекст: миграция заказов завершилась, количество строк совпало, и чтение переключили на новую базу. Через сутки часть клиентов увидела нулевые суммы заказов.
- Диагностика. Проверка ограничилась сравнением количества строк. Сумма заказа в новой схеме вычислялась из позиций, а для заказов, созданных до изменения структуры, позиции отсутствовали, поэтому сумма оказывалась нулевой.
- Причина. Сверка не включала агрегаты по значениям и проверку бизнес-правил. Совпадение числа строк было принято как подтверждение корректности.
- Действия. (а) Чтение вернули на старую базу, поскольку двойная запись продолжала работать; (б) добавили сравнение агрегатов: сумма, минимум, максимум и число уникальных значений по ключевым колонкам; (в) добавили проверку бизнес-правил: заказ без позиций считается ошибкой; (г) добавили сверку контрольных сумм по сегментам идентификаторов для локализации расхождений; (д) преобразование дополнили расчётом суммы из сохранённого значения для исторических заказов.
- Результат. Повторная сверка выявила 2 800 заказов с нулевой суммой до переключения чтения, а проверка бизнес-правил вошла в обязательный набор.
Вывод: совпадение количества строк не подтверждает корректность значений. Агрегаты по колонкам и проверка бизнес-правил выявляют систематические ошибки преобразования, которые иначе обнаруживаются пользователями после переключения.
FAQ
Достаточно ли сравнить количество строк? Нет. Количество выявляет потерю строк, но не неверные значения. Агрегаты и контрольные суммы по сегментам проверяют содержимое.
Как локализовать расхождение? Контрольными суммами по диапазонам идентификаторов. Несовпадение указывает на сегмент, внутри которого выполняется детальная сверка.
Что делать с изменяющимися данными во время сверки? Сравнивать состояние на определённый момент либо исключать записи, изменённые после начала сверки.
Как часто выполнять сверку? При двойной записи — по расписанию непрерывно. Однократная сверка пропускает расхождения, возникшие после неё.
Источники: PostgreSQL docs (агрегатные функции, строковые функции), Martin Fowler — ссылки в шапке.