Головна небезпека не в тривалості самої зміни, а в блокуваннях. ALTER TABLE у PostgreSQL бере ACCESS EXCLUSIVE-блокування. Якщо в цей момент іде довгий запит, ALTER стає в чергу - і всі нові запити до таблиці стають у чергу за ним. Сайт лягає, хоча сама операція займає мілісекунди.
Правила, що рятують:
SET lock_timeout = '3s'; -- краще впасти й повторити, ніж повісити таблицю
SET statement_timeout = '60s';
ALTER TABLE orders ADD COLUMN note text;
Що дешево, а що ні (PostgreSQL):
- Додати колонку без значення за замовчуванням чи з незмінним default (PostgreSQL 11+) - миттєво, лише метадані.
- Додати
NOT NULLдо наявної колонки - повна перевірка таблиці під блокуванням. Безпечніше:CHECK (col IS NOT NULL) NOT VALID, потімVALIDATE CONSTRAINT(без блокування запису), потімSET NOT NULL(PostgreSQL 12+ використає перевірене обмеження). - Зовнішній ключ - так само:
NOT VALID, потімVALIDATE. - Змінити тип колонки - часто переписування всієї таблиці. Краще нова колонка, поступове заповнення, перемикання.
- Індекс - лише
CONCURRENTLY.
Перейменування й видалення - через «розширити, потім звузити» (expand/contract):
- Додати нову колонку, код пише в обидві.
- Перенести старі дані порціями.
- Код читає з нової.
- Окремим деплоєм прибрати стару колонку.
Так кожен крок сумісний і з попередньою, і з наступною версією коду, і деплой можна відкотити.
MySQL: багато змін виконуються online (ALGORITHM=INSTANT для додавання колонки з 8.0), для решти - gh-ost чи pt-online-schema-change.