Найти в Дзене

🔤🔤🔤 OOMKiller - страшный сон Администратора баз данных

Попробуем выяснить основные причины, неочевидные особенности работы Лучшей в мире платформы 1С и возможно ли с этим что-то сделать… OOMKiller –система защиты Linux от перерасхода памяти. Срабатывает, убивая самый «толстый» по памяти процесс в Операционной системе при приближении расхода памяти к 95% Итак, в чём же вообще проблема? В том, что неожиданно падает сервер PostgreSQL и по системным логам мы понимаем что он пал жертвой убийства со стороны OOMKiller. Основной причиной такого поведения PostgreSQL является ошибка планировщика в том, где делать сортировку результата запроса. Ошибка планировщика чаще всего возникает из-за отсутствия актуальной статистики по базе – это корневая причина В итоге, при планировании запроса, планировщик уверен что сортировку можно произвести в памяти, так как по его прикидкам она влезет в параметр work_mem (например 256MB), так как получит на вход небольшое количество строк для сортировки и их размер тоже будет небольшим (например 100 строк, размером

🔤🔤🔤 OOMKiller - страшный сон Администратора баз данных.

Попробуем выяснить основные причины, неочевидные особенности работы Лучшей в мире платформы 1С и возможно ли с этим что-то сделать…

OOMKiller –система защиты Linux от перерасхода памяти.

Срабатывает, убивая самый «толстый» по памяти процесс в Операционной системе при приближении расхода памяти к 95%

Итак, в чём же вообще проблема?

В том, что неожиданно падает сервер PostgreSQL и по системным логам мы понимаем что он пал жертвой убийства со стороны OOMKiller.

Основной причиной такого поведения PostgreSQL является ошибка планировщика в том, где делать сортировку результата запроса.

Ошибка планировщика чаще всего возникает из-за отсутствия актуальной статистики по базе – это корневая причина

В итоге, при планировании запроса, планировщик уверен что сортировку можно произвести в памяти, так как по его прикидкам она влезет в параметр work_mem (например 256MB), так как получит на вход небольшое количество строк для сортировки и их размер тоже будет небольшим (например 100 строк, размером по 30КБ каждая). Эти данные планировщик получает из статистики.

Начав выполнение запроса СУБД уже не может ослушаться этой декларации планировщика и выполняет сортировку в памяти.

НО вместо предполагаемых 100 строк по 30КБ, что спокойно вмещается в 256МБ нам для сортировки прилетело 1,5млн строк по 30КБ, что уже занимает 42ГБ!

В итоге в процессе сортировки такого объёма в памяти, эта самая память или совсем закончится или её расход приблизится к уровню сработки OOMKiller-а.

Ситуацию усугубляется следующим:

❗️Убивать процессы нельзя! Это приведет к перезапуску всего PostgreSQL!

▫️work_mem устанавливается на каждое соединение. Т.е. у нас может сложится ситуация когда сразу несколько пользователей 1С сделают запрос к СУБД на такого рода сортировку…

▫️ Каждое соединение в PostgreSQL работает в отдельном процессе и при этом процесс не умеет худеть по памяти, он просто убивается как становится никому не нужным.

▫️ Платформа 1С удерживает idle соединения при необходимости (например в нём создавалась временная таблица и её можно будет переиспользовать) . Т.е. у нас может сложится ситуация, когда запрос выполнился, заняв 20ГБ RAM, при этом соединение удерживается и используется для других запросов, которым столько RAM не нужно.

Методы борьбы с этими негативными моментами:

❗️Убивать процессы нельзя! Это приведет к перезапуску всего PostgreSQL! А значит увидев что процесс работает (не idle) наш единственный шанс корректно завершить этот запрос, это отменить его выполнение на сервере 1С вычислив его по номеру соединения с СУБД.

▫️Необходимо содержать статистику в максимально актуальном состоянии. Настраивая агрессивный autovacuum, устанавливая нестандартные значения сработки autovacuum на больших таблицах, проводить vacuum analyze как регламентную операцию и т.д.

▫️Уменьшить work_mem, отслеживая как это повлияет и на план и на работу дисков

▫️Настроить OOMKiller. Чтобы он не убивал, а замораживал процесс OOMPolicy=continue, но это опасно, так как в итоге вся память может быть поглощена и работы вообще остановится.

▫️Отдельный пункт для борьбы с толстыми idle.

Мы можем вычислить ТОП-3 процессов, потребляющих память

ps -eo pmem,vsize,pid,cmd | sort -k 1 -nr | head -3

и увидеть такую картину:

6.6 12095572 2380533 postgres: postgres erp 10.27.24.1(64722) idle

6.6 12015844 2380844 postgres: postgres erp 10.27.24.1(64837) idle

6.4 12091534 2380682 postgres: postgres erp 10.27.24.1(64735) SELECT

Видим что в топе процессы с idle и только 1 с select.

В PostgreSQL есть параметр idle_session_timeout, по умолчанию 0.

Но мы можем выставить его в 3 сек, подождать 7 сек и обратно убрать в 0.

ALTER SYSTEM SET idle_session_timeout = 3000;

'select pg_reload_conf();

'ALTER SYSTEM RESET idle_session_timeout;

Таким образом мы корректно прервём соединения с 1С и СУБд сама корректно завершит наши объевшиеся процессы.

Негативный побочный эффект – временные таблицы платформе 1С придётся создать заново, но по сравнению с перезапуском СУБД это допустимо