До основного вмісту

Сервер під базу даних: залізо та налаштування

Виділені сервери · 24.09.2026
Ілюстрація до статті «Сервер під базу даних: залізо та налаштування»

Виділений сервер під базу даних: залізо й налаштування

База даних упирається в три речі за порядком: обсяг пам'яті, затримку диска на fsync і частоту ядра. Робочий набір даних має вміщатися в RAM, журнал транзакцій — лежати на NVMe, а масив бути RAID1 чи RAID10, але не RAID5. Пам'ять обов'язково ECC: тиха помилка в буферному пулі йде на диск як пошкоджена сторінка.

  • Пам'ять важливіша за ядра: доки робочий набір влазить у буферний пул, база читає з RAM, а не з диска.
  • NVMe проти SATA SSD дає рази на випадковому записі 8–16 KB — це профіль журналу та сторінок бази.
  • RAID10 для запису, RAID1 для пари дисків; RAID5 платить читанням і двома записами на кожен змінений блок.
  • ECC-пам'ять є на всіх тарифах ZevsHost; для бази це обов'язкова вимога, а не опція.
  • Половина «повільної бази» лікується індексами та innodb_buffer_pool_size, а не зміною сервера.

Що брати із заліза

КомпонентЧому він критичнийОрієнтир
RAMБуферний пул тримає гарячі сторінки; промах іде на диск1,3–1,5 обсягу гарячих даних, мінімум 16 GB
Дискиfsync журналу виконується синхронно на кожному комітіNVMe; SATA SSD лише під невелике навантаження
CPUОдин запит виконується одним ядромЧастота важливіша за кількість ядер, якщо запити важкі
RAIDВтрата диска не має зупиняти базуRAID1 на два диски, RAID10 на чотири
Пам'ять ECCПобита сторінка з RAM записується на диск як валіднаОбов'язково, DDR4 ECC

Різниця між накопичувачами розібрана у статті про NVMe, SATA SSD і жорсткі диски, вибір рівня масиву — в матеріалі про рівні RAID. Під базу беруть Pro (32 GB, 2×1 TB NVMe, RAID1) або Enterprise US (64 GB, 4×1 TB NVMe, RAID10); перелік — на сторінці виділених серверів.

Налаштування MySQL і MariaDB

Де крім бази майже нічого немає, буферному пулу віддають 60–70% пам'яті. Решта йде з'єднанням, тимчасовим таблицям і кешу.

# /etc/mysql/mariadb.conf.d/60-tuning.cnf
[mysqld]
# сервер на 32 GB: пул приблизно 20 GB
innodb_buffer_pool_size = 20G
innodb_buffer_pool_instances = 8
# 1 = повна довговічність, транзакція не втрачається
innodb_flush_log_at_trx_commit = 1
innodb_log_file_size = 2G
innodb_flush_method = O_DIRECT
# NVMe витримує значно більше за типове значення
innodb_io_capacity = 4000
innodb_io_capacity_max = 8000
max_connections = 300
tmp_table_size = 256M
max_heap_table_size = 256M
# відновлення дампу і перевірка реального розміру пулу
systemctl restart mariadb
mysql -u root -p mydb < /backup/mydb.sql

mysql -u root -p -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"
# частка влучань у пул: дивимось Innodb_buffer_pool_reads проти ..._read_requests
mysql -u root -p -e "SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';" 2>&1 | tee pool.txt

Якщо Innodb_buffer_pool_reads зростає на усталеному навантаженні, гарячі дані не вміщуються в пул: додавайте пам'ять або скорочуйте вибірки. Встановлення і права — у статті про налаштування MariaDB.

Налаштування PostgreSQL

PostgreSQL ділить пам'ять інакше: shared_buffers беруть близько 25% RAM, а effective_cache_size виставляють у 60–75% як підказку планувальнику.

# postgresql.conf, сервер із 32 GB
shared_buffers = 8GB
effective_cache_size = 24GB
maintenance_work_mem = 2GB
work_mem = 32MB
wal_buffers = 64MB
max_wal_size = 8GB
checkpoint_completion_target = 0.9
# NVMe: випадкове читання майже не дорожче за послідовне
random_page_cost = 1.1
effective_io_concurrency = 200
synchronous_commit = on
# застосовуємо і перевіряємо, що значення прийняті
systemctl restart postgresql
sudo -u postgres psql -c "SHOW shared_buffers;" -c "SHOW random_page_cost;"

# відновлення з дампу
sudo -u postgres psql mydb < /backup/mydb.sql
sudo -u postgres pg_restore -d mydb -j 4 /backup/mydb.dump 2>&1 | tail -20

З'єднання, автентифікація та автовакуум розібрані у статті про PostgreSQL на сервері.

Як перевірити, що диск тягне базу

Тест має повторювати профіль бази: випадковий запис блоками 16 KB з fsync, а не послідовне читання.

# профіль, близький до навантаження InnoDB
fio --name=dbwrite --rw=randwrite --bs=16k --iodepth=32 --numjobs=4 \
    --size=4G --runtime=120 --time_based --direct=1 --fsync=1 \
    --filename=/var/lib/mysql/fiotest --group_reporting

# затримка коміту в мікросекундах: критична саме вона
fio --name=commit --rw=write --bs=4k --iodepth=1 --sync=1 \
    --size=1G --runtime=60 --time_based --direct=1 \
    --filename=/var/lib/mysql/fiotest 2>&1 | grep -E 'lat|IOPS'

Дивіться не на пікові IOPS, а на затримку 99-го процентиля: саме вона дає «сайт іноді підвисає». Методика заміру — в матеріалі про бенчмарк сервера через fio та sysbench.

Спокуса виставити innodb_flush_log_at_trx_commit = 0 чи synchronous_commit = off дає помітний приріст запису, але означає рівно одне: за відмови живлення або падіння процесу ви втрачаєте підтверджені клієнту транзакції. Для платежів і складських залишків це неприпустимо. Друге: не кладіть базу на RAID5 заради ємності — кожен запис блоку перетворюється на читання і два записи. Перевіряйте довговічність тестом: запустіть навантаження, зніміть живлення через IPMI, підніміть базу і порівняйте останню підтверджену транзакцію з тим, що лишилося в таблиці.

Коротко

  • Порядок пріоритетів: пам'ять під робочий набір, далі NVMe під журнал, далі частота ядра.
  • MySQL: пул 60–70% RAM, flush_log_at_trx_commit = 1, io_capacity під NVMe.
  • PostgreSQL: shared_buffers близько 25% RAM, effective_cache_size 60–75%, random_page_cost 1.1 на NVMe.
  • Диск перевіряють випадковим записом 16 KB з fsync, дивляться затримку 99-го процентиля, а не пік IOPS.
  • RAID1 або RAID10; вимкнення довговічності заради швидкості коштує втрачених транзакцій.
← Назад до бази знань Поставити питання підтримці