[Перевод] Настройка параметров ядра Linux для оптимизации PostgreSQL
Оптимальная производительность PostgreSQL зависит от правильно определенных параметров операционной системы. Плохо настроенные параметры ядра ОС могут привести к снижению производительности сервера базы данных. Поэтому обязательно, чтобы эти параметры были настроены в соответствии с сервером базы данных и его рабочей нагрузкой. В этом посте мы обсудим некоторые важные параметры ядра Linux, которые могут повлиять на производительность сервера базы данных и способы их настройки.
SHMMAX / SHMALL
SHMMAX — это параметр ядра, используемый для определения максимального размера одного сегмента разделяемой памяти (shared memory), который может выделить процесс Linux. До версии 9.2 PostgreSQL использовал System V (SysV), для которой требуется настройка SHMMAX. После 9.2 PostgreSQL переключился на разделяемую память POSIX. Так что теперь требуется меньше байтов разделяемой памяти System V.
До версии 9.3 SHMMAX был наиболее важным параметром ядра. Значение SHMMAX задается в байтах.
Аналогично, SHMALL — это еще один параметр ядра, используемый для определения
общесистемного объема страниц разделяемой памяти (shared memory). Чтобы просмотреть текущие значения SHMMAX, SHMALL или SHMMIN, используйте команду ipcs.
SHM* Details — Linux
$ ipcs -lm
------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 1073741824
max total shared memory (kbytes) = 17179869184
min seg size (bytes) = 1
SHM* Details — MacOS X
$ ipcs -M
IPC status from as of Thu Aug 16 22:20:35 PKT 2018
shminfo:
shmmax: 16777216 (max shared memory segment size)
shmmin: 1 (min shared memory segment size)
shmmni: 32 (max number of shared memory identifiers)
shmseg: 8 (max shared memory segments per process)
shmall: 1024 (max amount of shared memory in pages)
PostgreSQL использует System V IPC для выделения разделяемой памяти. Этот параметр является одним из наиболее важных параметров ядра. Всякий раз, когда вы получаете следующие сообщения об ошибках, это означает, что у вас более старая версия PostgreSQL и у вас очень низкое значение SHMMAX. Ожидается, что пользователи будут корректировать и увеличивать значение в соответствии с разделяемой памятью, которую они собираются использовать.
Возможные ошибки неправильной конфигурации
Если SHMMAX настроен неправильно, вы можете получить ошибку при попытке инициализировать кластер PostgreSQL с помощью команды initdb.
initdb FailureDETAIL: Failed system call was shmget(key=1, size=2072576, 03600).
HINT: This error usually means that PostgreSQL’s request for a shared memory segment exceeded your kernel’s SHMMAX parameter.
You can either reduce the request size or reconfigure the kernel with larger SHMMAX. To reduce the request size (currently 2072576 bytes),
reduce PostgreSQL’s shared memory usage, perhaps by reducing shared_buffers or max_connections.
If the request size is already small, it’s possible that it is less than your kernel’s SHMMIN parameter,
in which case raising the request size or reconfiguring SHMMIN is called for.
The PostgreSQL documentation contains more information about shared memory configuration. child process exited with exit code 1
Аналогично, вы можете получить ошибку при запуске сервера PostgreSQL используя команду pg_ctl.
pg_ctl FailureDETAIL: Failed system call was shmget(key=5432001, size=14385152, 03600).
HINT: This error usually means that PostgreSQL’s request for a shared memory segment exceeded your kernel’s SHMMAX parameter.
You can either reduce the request size or reconfigure the kernel with larger SHMMAX.; To reduce the request size (currently 14385152 bytes), reduce PostgreSQL’s shared memory usage, perhaps by reducing shared_buffers or max_connections.
If the request size is already small, it’s possible that it is less than your kernel’s SHMMIN parameter,
in which case raising the request size or reconfiguring SHMMIN is called for.
The PostgreSQL documentation contains more information about shared memory configuration.
Понимание различий в определениях
Определение параметров SHMMAX/SHMALL немного отличается в Linux и MacOS X:
- Linux: kernel.shmmax, kernel.shmall
- MacOS X: kern.sysv.shmmax, kern.sysv.shmall
Команда sysctl может быть использована для временного изменения значения. Чтобы установить постоянные значения, добавьте запись в /etc/sysctl.conf. Подробности приведены ниже.
Изменение параметров ядра на MacOS X
# Get the value of SHMMAX
sudo sysctl kern.sysv.shmmax
kern.sysv.shmmax: 4096
# Get the value of SHMALL
sudo sysctl kern.sysv.shmall
kern.sysv.shmall: 4096
# Set the value of SHMMAX
sudo sysctl -w kern.sysv.shmmax=16777216
kern.sysv.shmmax: 4096 -> 16777216
# Set the value of SHMALL
sudo sysctl -w kern.sysv.shmall=16777216
kern.sysv.shmall: 4096 -> 16777216
Изменение параметров ядра на Linux
# Get the value of SHMMAX
sudo sysctl kernel.shmmax
kernel.shmmax: 4096
# Get the value of SHMALL
sudo sysctl kernel.shmall
kernel.shmall: 4096
# Set the value of SHMMAX
sudo sysctl -w kernel.shmmax=16777216
kernel.shmmax: 4096 -> 16777216
# Set the value of SHMALL
sudo sysctl -w kernel.shmall=16777216
kernel.shmall: 4096 -> 16777216
Не забудьте: чтобы сделать изменения постоянными, добавьте эти значения в /etc/sysctl.conf
Большие страницы (Huge Pages)
В Linux по умолчанию используются страницы памяти 4 КБ, в BSD — Super Pages, а в Windows — Large Pages. Страница — это часть оперативной памяти, выделенная процессу. Процесс может иметь несколько страниц в зависимости от требований к памяти. Чем больше памяти требуется процессу, тем больше страниц ему выделено. ОС поддерживает таблицу выделения страниц для процессов. Чем меньше размер страницы, тем больше таблица, тем больше времени требуется для поиска страницы в этой таблице страниц. Поэтому большие страницы позволяют использовать большой объем памяти с уменьшенными накладными расходами; меньше просмотров страниц, меньше ошибок страниц, более быстрые операции чтения/записи через большие буферы. Как результат — улучшение производительности.
PostgreSQL поддерживает большие страницы только в Linux. По умолчанию Linux использует 4 КБ страниц памяти, поэтому в случаях, когда операций с памятью слишком много, необходимо устанавливать страницы большего размера. Наблюдается прирост производительности при использовании больших страниц размером 2 МБ и до 1 ГБ. Размер большой страницы может быть установлен во время загрузки. Вы можете легко проверить параметры большой страницы и их использование на вашем Linux-компьютере, используя команду cat /proc/meminfo | grep -i huge.
Получение информации о больших страницах (только на Linux)
Note: This is only for Linux, for other OS this operation is ignored$ cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
В этом примере, хотя размер большой страницы установлен в 2048 (2 МБ), общее количество больших страниц имеет значение 0. Это означает, что большие страницы отключены.
Скрипт определения количества больших страниц
Это простой скрипт возвращает необходимое количество больших страниц. Запустите скрипт на вашем сервере Linux, пока работает PostgreSQL. Убедитесь, что для переменной среды $PGDATA задан каталог данных PostgreSQL.
Получение цифры требуемых больших страниц
#!/bin/bash
pid=`head -1 $PGDATA/postmaster.pid`
echo "Pid: $pid"
peak=`grep ^VmPeak /proc/$pid/status | awk '{ print $2 }'`
echo "VmPeak: $peak kB"
hps=`grep ^Hugepagesize /proc/meminfo | awk '{ print $2 }'`
echo "Hugepagesize: $hps kB"
hp=$((peak/hps))
echo Set Huge Pages: $hp
Вывод скрипта выглядит следующим образом:
Вывод скрипта
Pid: 12737
VmPeak: 180932 kB
Hugepagesize: 2048 kB
Set Huge Pages: 88
Рекомендуемое значение больших страниц — 88, поэтому вы должны установить значение 88.
Установка больших страниц
sysctl -w vm.nr_hugepages=88
Проверьте большие страницы сейчас, вы увидите, что большие страницы не используются (HugePages_Free = HugePages_Total).
Снова информация о больших страницах (только на Linux)
$ cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 88
HugePages_Free: 88
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Теперь задайте параметр huge_pages «on» в $PGDATA/postgresql.conf и перезапустите сервер.
И снова информация о больших страницах (только на Linux)
$ cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 88
HugePages_Free: 81
HugePages_Rsvd: 64
HugePages_Surp: 0
Hugepagesize: 2048 kB
Теперь вы можете видеть, что используются очень мало больших страниц. Давайте теперь попробуем добавить некоторые данные в базу данных.
Некоторые операции с базой данных для утилизации больших страниц
postgres=# CREATE TABLE foo(a INTEGER);
CREATE TABLE
postgres=# INSERT INTO foo VALUES(generate_Series(1,10000000));
INSERT 0 10000000
Давайте посмотрим, используем ли мы сейчас больше больших страниц, чем раньше.
Еще раз информация о больших страницах (только на Linux)
$ cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 88
HugePages_Free: 18
HugePages_Rsvd: 1
HugePages_Surp: 0
Hugepagesize: 2048 kB
Теперь вы можете видеть, что большинство больших страниц используется.
Примечание: примерное значение для HugePages, используемое здесь, очень низкое, что не является нормальным значением для машины на продуктовой среде. Пожалуйста, оцените необходимое количество страниц для вашей системы и установите их соответственно в зависимости от нагрузки и ресурсов.
vm.swappiness
vm.swappiness — это еще один параметр ядра, который может влиять на производительность базы данных. Этот параметр используется для управления поведением подкачки (swappiness) (подкачки страниц в память и из нее) в Linux. Значение варьируется от 0 до 100. Он определяет, сколько памяти будет выгружено или выгружено. Ноль означает отключение обмена, а 100 означает агрессивный обмен.
Вы можете получить хорошую производительность, установив более низкие значения.
Установка значения 0 в более новых ядрах может привести к тому, что OOM Killer (процесс очистки памяти в Linux) убьет процесс. Таким образом, можно безопасно установить значение 1, если хотите минимизировать подкачку. Значение по умолчанию в Linux — 60. Более высокое значение заставляет MMU (блок управления памятью) использовать больше пространства подкачки, чем ОЗУ, тогда как более низкое значение сохраняет больше данных/кода в памяти.
Меньшее значение — хорошая ставка на улучшение производительности в PostgreSQL.
vm.overcommit_memory / vm.overcommit_ratio
Приложения получают память и освобождают ее, когда она больше не нужна. Но в некоторых случаях приложение получает слишком много памяти и не освобождает ее. Это может вызвать OOM killer. Вот возможные значения параметра vm.overcommit_memory с описанием для каждого:
- Эвристический overcommit (по умолчанию); основанная на ядре эвристика
- Разрешить overcommit в любом случае
- Не переусердствуйте, не превышайте overcommit коэффициент.
Ссылка: https://www.kernel.org/doc/Documentation/vm/overcommit-accounting
vm.overcommit_ratio — процент оперативной памяти, доступной для чрезмерной загрузки. Значение 50% в системе с 2 ГБ ОЗУ может выделять до 3 ГБ ОЗУ.
Значение 2 для vm.overcommit_memory обеспечивает лучшую производительность для PostgreSQL. Это значение максимизирует использование оперативной памяти серверным процессом без какого-либо значительного риска быть убитым процессом OOM killer. Приложение сможет перезагружаться, но только в пределах перерасхода, что снижает риск того, что OOM killer убьет процесс. Следовательно, значение 2 дает лучшую производительность, чем значение по умолчанию 0. Тем не менее, надежность может быть улучшена за счет того, что память за пределами допустимого диапазона не будет перегружена. Это исключает риск того, что процесс будет убит OOM-killer.
В системах без подкачки может возникнуть проблема с vm.overcommit_memory равным 2.
https://www.postgresql.org/docs/current/static/kernel-resources.html#LINUX-MEMORY-OVERCOMMIT
vm.dirty_background_ratio / vm.dirty_background_bytes
vm.dirty_background_ratio — это процент памяти, заполненной грязными страницами, которые необходимо записать на диск. Сброс на диск производится в фоновом режиме. Значение этого параметра колеблется от 0 до 100; однако значение ниже 5 может быть неэффективным, и некоторые ядра его не поддерживают. 10 — значение по умолчанию в большинстве систем Linux. Вы можете повысить производительность для операций с интенсивной записью с меньшим коэффициентом, который будет означать, что Linux будет сбрасывать грязные страницы в фоновом режиме.
Вам нужно установить значение vm.dirty_background_bytes в зависимости от скорости вашего диска.
Для этих двух параметров нет «хороших» значений, так как оба зависят от аппаратного обеспечения. Однако установка vm.dirty_background_ratio в значение 5 и vm.dirty_background_bytes в 25% от скорости диска, повышает производительность до ~ 25% в большинстве случаев.
vm.dirty_ratio / dirty_bytes
Это то же самое, что vm.dirty_background_ratio / dirty_background_bytes, за исключением того, что сброс выполняется в рабочем сеансе, блокируя приложение. Поэтому vm.dirty_ratio должно быть выше, чем vm.dirty_background_ratio. Это гарантирует, что фоновые процессы будут запускаться раньше, чтобы избежать максимально возможной блокировки приложения. Вы можете настроить разницу между этими двумя соотношениями в зависимости от загрузки дискового ввода-вывода.
Итог
Вы можете настроить другие параметры для увеличения производительности, но улучшения будут минимальными и выгоды особой не получите. Мы должны помнить, что не все параметры относятся ко всем типам приложений. Некоторые приложения работают лучше, когда мы настраиваем некоторые параметры, а некоторые — нет. Вы должны найти правильный баланс между конфигурациями этих параметров для ожидаемой рабочей нагрузки и типа приложения, а также при настройке необходимо учитывать поведение ОС. Настроить параметры ядра не так просто, как настроить параметры базы данных: здесь сложнее давать свои рекомендации.