Код-ревью Senior Базы данных в эксплуатации обновлено
Код-ревью: миграция на горячей таблице
Вопрос
Миграция применяется на проде к таблице orders (80 млн строк, постоянная запись) во время rolling-деплоя новой версии кода. PostgreSQL 16. Найдите проблемы.
BEGIN;
ALTER TABLE orders ADD COLUMN status text NOT NULL DEFAULT 'new';
CREATE INDEX idx_orders_user ON orders (user_id);
ALTER TABLE orders ALTER COLUMN amount TYPE numeric(12,2);
ALTER TABLE orders RENAME COLUMN comment TO note;
ALTER TABLE orders ADD CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users (id);
UPDATE orders SET status = 'done' WHERE paid_at IS NOT NULL;
COMMIT;
Коротко
Строка 2 здесь как раз безопасна: с PostgreSQL 11 добавление колонки с константным DEFAULT не переписывает таблицу. Остальное классика опасных миграций.
Что должен найти ревьюер
- Ошибкастрока 1Всё в одной транзакции: блокировка ACCESS EXCLUSIVE, взятая первым ALTER, держится до COMMIT, то есть на всё время индекса, перезаписи и UPDATE. Таблица недоступна минутами. Разбить на отдельные шаги и задать
lock_timeout. - Производительностьстрока 3Индекс без
CONCURRENTLYблокирует запись на время построения. - Производительностьстрока 4Смена типа на numeric(12,2) переписывает всю таблицу под эксклюзивной блокировкой. Через новую колонку и бэкфилл.
- Ошибкастрока 5Переименование колонки во время rolling: старые поды ещё обращаются к
commentи падают. Только expand/contract. - Производительностьстрока 6Внешний ключ проверяет все 80 млн строк под блокировкой. Сначала
NOT VALID, потомVALIDATE CONSTRAINT. - Производительностьстрока 7UPDATE миллионов строк одним запросом: долгие блокировки строк, раздувание таблицы, лаг репликации. Пачками по несколько тысяч.
Разбор
Строка 2 здесь как раз безопасна: с PostgreSQL 11 добавление колонки с константным DEFAULT не переписывает таблицу. Остальное классика опасных миграций. Правильный порядок: короткие отдельные шаги с lock_timeout, индексы конкурентно, ограничения через NOT VALID, переименования и смены типа через новую колонку, бэкфилл пачками отдельной задачей.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.