Индекс concurrently...
 
Уведомления
Очистить всё

Индекс concurrently упал посреди ночи и остался INVALID. Что с ним делать?

6 Сообщения
5 Пользователи
2 Реакции
303 Просмотры
Егор64
Сообщения: 30
Автор темы
Читает чужие PR тимлид
Присоединился: 3 года назад
[#69]

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

class AddIndexOnEventsAccountIdCreatedAt < ActiveRecord::Migration[7.2]
  disable_ddl_transaction!

  def change
    add_index :events, [:account_id, :created_at], algorithm: :concurrently
  end
end

Через сорок минут деплой отвалился по таймауту в CI, миграция упала, в schema_migrations записи нет. Алерт увидел утром ещё в метро от Беговой, на работе открываю \d events, а индекс там есть, только с пометкой INVALID. Повторный запуск миграции падает, потому что индекс уже существует. Он вообще используется в таком виде? И как повторить, чтобы не повесить прод днём? Rails 7.2, PostgreSQL 16.


5 ответов
kostya.sokurov
Сообщения: 73
Держит прод бэкенд-разработчик, senior
Присоединился: 4 года назад

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

SELECT indexrelid::regclass AS index_name,
       indrelid::regclass AS table_name
FROM pg_index
WHERE NOT indisvalid;

Дальше либо DROP INDEX CONCURRENTLY и заново, либо пересобрать. И не гоняйте такие миграции внутри деплоя с таймаутом CI: сорок минут для составного индекса на 30 млн строк вполне нормальная цифра.


Ответ
Степан Ф
Сообщения: 3
Пишет в irb тимлид
Присоединился: 4 года назад

В 16-м проще REINDEX INDEX CONCURRENTLY имя_индекса, он пересоберёт невалидный на месте, удалять не нужно.


Ответ
Егор64
Сообщения: 30
Автор темы
Читает чужие PR тимлид
Присоединился: 3 года назад

Пересобрал через REINDEX CONCURRENTLY из psql в обед, ушло 37 минут, запросы не тормозили. В миграцию дописал if_not_exists: true и прогнал, она просто проскочила и записалась в schema_migrations. Нам такое повторять ещё на двух таблицах. Как вы отделяете тяжёлые миграции от обычного деплоя?


Ответ
armen_pet
Сообщения: 30
Собрал свой gem DevOps-инженер
Присоединился: 4 года назад

Долгие миграции я бы из деплоя убрал совсем. В пайплайне идут только быстрые, а тяжёлые помечаются и запускаются отдельной ручной джобой в CI, ночью, без сорокаминутного таймаута и с большим statement_timeout на сессию. И пусть в это время кто-то не спит и смотрит на графики, а не узнаёт утром из алертов.


Ответ
GalinaKorneva
Сообщения: 30
Читает чужие PR бэкенд-разработчица
Присоединился: 4 года назад

strong_migrations ещё поставьте, он add_index без concurrently просто не пропустит. Новые люди в команде забывают про это чаще всего.


Ответ