По моим наблюдениям, куча народу мучается с МуSQL на мелких виртуалках, ибо он мало что прожорлив на память, так еще и имеет привычку падать по ее нехватке. Решение у этой проблемы есть, но самое популярное «решение» от Гугля на самом деле не работает. Что работает — читаем дальше.
Проблема в том, что MySQL в последних версиях невероятно прожорлив на память, и, что особенно печально, никакими параметрами конфигурации невозможно заставить его вести себя иначе. Нынче малые VPS можно купить за сущие копейки, и многие переводят свои небольшие проекты с shared хостинга на VPS. И вот тут начинаются скачки по граблям, одними из самых мощных является постоянное падение MySQL. Причем если старые версии падают и лежат, приводя к неработоспособности сервиса, то 5.7 сама падает, сама встает, создавая иллюзию жизнеспособности.
Первое, что советуют везде — урезать параметр innodb_buffer_pool_size, который по умолчанию равен 128М. Урезание его до 64 или даже до 32М несколько стабилизирует работу системы, т.е. падения случаются существенно реже. Но это — до первой нагрузки, поскольку память остается «слабым местом», высвободилось ее немного.
Более радикальное решение этой проблемы, приводящее к полной стабилизации системы в том, чтобы добавить swap, увеличив количество доступной памяти, как это рекомендует делать DigitalOcean. Сделать это, увы любителям всяких контрольных панелей, можно только из консоли сервера с правами root.
Итак, пошагово, для линукс-систем на базе RedHat, то есть все версии CentOs, Ubuntu и так далее. Хотя по идее и на других дистрибутивах должно работать. Все команды от root. Подразумеваем, что Вы умеете пользоваться sudo, потому что обычный вход от рута — очень плохая практика.
1. создаем файл нужного размера
dd if=/dev/zero of=/swapfile bs=1024 count=1024k
Здесь count — число блоков по 1024 байта, т.е. по сути размер свопа в килобайтах. В примере задан 1 гиг. Имя файла — swapfile, расположение — корневой каталог файловой системы.
2. Устанавливаем права правильно
chmod 0600 /swapfile
3. Форматируем этот файл именно своп-файлом
mkswap /swapfile
4. Подключаем своп
swapon /swapfile
Теперь если мы посмотрим состояние свопа командой «swapon -s», то мы увидим:
[root@pavlyuts /]# swapon -s Filename Type Size Used Priority /swapfile file 1048572 0 -1 [root@pavlyuts /]#
Собственно, своп-файл уже подключен, остался дополнительный, весьма важный тюнинг.
5. Чтобы своп пережил перезагрузку необходимо внести его в таблицу разделов. Любым доступным Вам редактором необходимо открыть файл /etc/fstab и добавить туда строку:
/swapfile none swap sw 0 0
6. Отдельный тонкий момент: мы расширили память системы за счет свопа, но чтобы не убить производительность нам надо сказать ядру, что своп — он на самый черный день, если памяти совсем не хватает. Политикой выгрузки страниц памяти в своп управляет параметр swappiness, обозначающий число процентов свободной памяти при которых надо начинать использовать своп. Корифеи рекомендуют в нашем случае установить его в 10.
echo 10 | tee /proc/sys/vm/swappiness
И добавить параметр в скрипт чтобы не потерять при перезагрузке.
echo vm.swappiness = 10 | tee -a /etc/sysctl.conf
Все, доступная память системы увеличилась на 1 гигабайт «резерва».
Конкретно для моего сервера 1CPU/1G/SSD, на котором крутится вот этот самый блог, в «состоянии покоя» результат выглядит вот так:
[pavlyuts@pavlyuts /]$ free total used free shared buff/cache available Mem: 1016908 480160 198684 7264 338064 392560 Swap: 1048572 0 1048572
Казалось бы, своп не используется и мы сделали что-то совершенно бессмысленное. Однако стоит как следует нагрузить его запросами (например, задать с другого хоста ab -n 500 -c 20 https://pavlyuts.ru/), то ситуация меняется радикально, на скриншоте самые большие значения использования в серии.
[pavlyuts@pavlyuts /]$ free total used free shared buff/cache available Mem: 1016908 828448 119716 200 68744 89828 Swap: 1048572 467812 580760
Как видим, в пике расходуется еще почти полгигабайта памяти. При этом отдача страниц, естественно, нещадно тупит, но система сохраняет работоспособность. Как показали предыдущие эксперименты, при попытке дать такую нагрузку без свопа MySQL падает независимо от ухищрений в конфигурации, здесь же просто следующим «узким местом» стал процессор.
Еще одним популярным решением является использования MariaDB вместо MySQL. Не смотря на то, что Мария намного более экономно использует память, при больших нагрузках и малом количестве памяти результат будет тот же. Поэтому для MariaDB данный способ так же рекомендован.
P.S. Благодаря умелым рукам и умной голове Дмитрия, которому огромное спасибо за тюнинг, по состоянию на сегодня в связке nginx/php-fpm/mysql вообще без кэширования и прочих ухищрений домашняя страница отдается со скоростью где-то 2,5 rps, статика — около 42 rps. это соответствует как минимум 5..7 тыс. запросов в час. И все это на сервере за 200 рублей в месяц. Осталось стать настолько популярным!