Налаштування параметрів ядра Linux для оптимізації PostgreSQL

Налаштування параметрів ядра 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, використовуйте команду шт.

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 використовує Система V IPC для виділення пам'яті, що розділяється. Цей параметр є одним із найважливіших параметрів ядра. Щоразу, коли ви отримуєте такі повідомлення про помилки, це означає, що у вас більш стара версія PostgreSQL і у вас дуже низьке значення SHMMAX. Очікується, що користувачі будуть коригувати і збільшувати значення відповідно до пам'яті, яку вони збираються використовувати.

Можливі помилки неправильної конфігурації

Якщо SHMMAX неправильно налаштований, ви можете отримати помилку при спробі ініціалізувати кластер PostgreSQL за допомогою команди initdb.

initdb Failure
DETAIL: 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 Failure
DETAIL: 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 — Супер-сторінки, а в 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 з описом для кожного:

  1. Евристичний overcommit (за умовчанням); заснована на ядрі евристика
  2. Дозволити overcommit у будь-якому випадку
  3. Чи не перестарайтеся, не перевищуйте 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. Це гарантує, що фонові процеси запускатимуться раніше, щоб уникнути максимально можливого блокування програми. Ви можете налаштувати різницю між цими двома співвідношеннями залежно від завантаження дискового вводу-виводу.

Підсумок

Ви можете налаштувати інші параметри для збільшення продуктивності, але покращення будуть мінімальними і вигоди особливої ​​не отримаєте. Ми повинні пам'ятати, що не всі параметри стосуються всіх типів програм. Деякі програми працюють краще, коли ми налаштовуємо деякі параметри, а деякі ні. Ви повинні знайти правильний баланс між конфігураціями цих параметрів для очікуваного робочого навантаження та типу програми, а також при налаштуванні необхідно враховувати поведінку ОС. Налаштувати параметри ядра не так просто, як налаштувати параметри бази даних: тут важче давати свої рекомендації.

Джерело: habr.com

Додати коментар або відгук