Виділений сервер під базу даних: залізо й налаштування
База даних упирається в три речі за порядком: обсяг пам'яті, затримку диска на 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; вимкнення довговічності заради швидкості коштує втрачених транзакцій.