Оптимизация ввода-вывода в MySQL: innodb_io_capacity и innodb_flush_method
- Высокий процент
%iowaitв выводе утилитыtopпри активной записи в БД. - Утилизация диска по
iostat -xz 1держится около 100% при низкой пропускной способности. - Просадки транзакций (checkpoint stalls) из-за медленного сброса грязных страниц из Buffer Pool.
- Двойное кэширование страниц памяти в оперативной памяти Linux и пуле InnoDB.
1. Конфигурация дискового I/O под Enterprise NVMe/SSD
Отредактируйте /etc/mysql/my.cnf в секции [mysqld]:
[mysqld]
# Исключение двойной буферизации ядра Linux (прямая запись на диск)
innodb_flush_method = O_DIRECT
# Количество фоновых операций ввода-вывода в секунду
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000
# Количество потоков чтения и записи
innodb_read_io_threads = 8
innodb_write_io_threads = 8
# Алгоритм очистки грязных страниц
innodb_flush_neighbors = 0
innodb_max_dirty_pages_pct = 75
innodb_max_dirty_pages_pct_lwm = 50
# Частота сброса транзакций на диск (1 - надежность, 2 - максимальная производительность)
innodb_flush_log_at_trx_commit = 12. Применение параметров в рантайме
SET GLOBAL innodb_io_capacity = 2000;
SET GLOBAL innodb_io_capacity_max = 4000;
SET GLOBAL innodb_flush_neighbors = 0;3. Оптимизация планировщика ввода-вывода в Linux
Для блочных устройств NVMe установите планировщик none:
echo none > /sys/block/nvme0n1/queue/scheduler Частые вопросы (FAQ)
Зачем отключать innodb_flush_neighbors на SSD/NVMe?
Сброс соседних страниц (flush neighbors) создавался для классических HDD с вращающимися пластинами ради снижения позиционирования головки. На SSD случайный доступ мгновенен, и сброс лишних страниц создает бесполезную нагрузку на шину памяти.
Когда можно использовать innodb_flush_log_at_trx_commit = 2?
В средах, где допустима потеря транзакций за последние 1-2 секунды при внезапном сбое питания сервера (реплики только для чтения, тестовые среды, сбор логов/метрик).