К основному содержимому

Выделенный сервер под базу данных: железо и настройка

Выделенные серверы · 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 и HDD, выбор уровня массива — в материале про уровни 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; отключение долговечности ради скорости стоит транзакций.
← Назад в базу знаний Задать вопрос поддержке