Задержка репликации — превышение max_slot_wal_keep_size, сегменты WAL не удалены

#postgresql #replication #wal #postgresql-13

Вопрос:

Краткие сведения

Мы используем max_slot_wal_keep_size от Postgresql 13, чтобы предотвратить гибель мастера из-за запаздывающей репликации. Похоже, что в нашем случае хранилище WAL не было освобождено после превышения этого параметра, что привело к сбою репликации. WAL, который, как я полагаю, должен был быть освобожден, казалось, не требовался для какой-либо другой транзакции в то время. Интересно, как это должно работать и почему сегменты WAL не были удалены?

Пожалуйста, ознакомьтесь с подробной информацией ниже.

Конфигурация

  • мастер и одна реплика — потоковая репликация с использованием слота
  • ~700 ГБ доступно для pg_wal
  • max_slot_wal_keep_size = 600GB
  • min_wal_size = 20GB
  • max_wal_size = 40GB
  • по умолчанию checkpoint_timeout = 5 минут (нет проблем с контрольными точками)
  • архивирование продолжается и идет полным ходом

Что случилось

При большой нагрузке (большие транзакции КОПИРОВАНИЯ/ВСТАВКИ, загрузка сотен ГБ данных) репликация начала отставать. Доступное пространство на pg_wal сокращалось с той же скоростью pg_replication_slot.safe_wal_size , что и safe_slot — как и ожидалось. В какой-то момент safe_wal_size пошел негатив, и потоковая передача перестала работать. Это не было проблемой, потому что реплика начала восстановление из архива WAL. Я ожидал, что как только слот будет потерян, WALs будет удален до max_wal_size . Однако этого не произошло. Похоже, что Postgres пытался поддерживать что-то близкое к max_slot_wal_keep_size (600 ГБ), доступному, на случай, если реплика снова начнет догонять. За все это время не было ни одной транзакции, которая потребовала бы хранения такого количества WAL. я тоже не отставал.

  • Q1: Это тот случай, когда PG попытается сохранить max_slot_keep_size доступные WALS?
  • Q2: Если нет, то почему PG не удалял избыточные WAL, когда они не были нужны ни архиватору, ни каким-либо транзакциям, выполняемым в системе?

Объем свободного места на pg_wal большую часть времени составлял более или менее 70 ГБ, однако в какой-то момент во время интенсивной автовакуумации он снизился до 0 🙁 Это когда PG разбился и (вскоре после этого автоматически восстановился). После восстановления на pg_wal осталось 11 ГБ, и транзакция не выполнялась, не загружалась. Это продолжалось несколько часов. За это время реплика наконец-то восстановилась из архива и восстановила репликацию без задержек. Ни одна из стенок не была удалена. Я вручную запустил контрольную точку, но она не очистила никаких WALS. Я, наконец, перезапустил Postgresql, и во время перезапуска pg_wal были окончательно очищены.

  • Вопрос 3: Опять же — почему PG не очистил WAL? ВАЛс, что еще более очевидно, не был нужен ни одному процессу.

Большое спасибо!

Ответ №1:

Это была ошибка PostgreSQL, и теперь она исправлена. Спасибо за репортаж!