Как вы, возможно, знаете, иногда MySQL может потребовать много памяти. Конечно, наличие данных в памяти всегда лучше, чем на диске… ОЗУ по-прежнему намного быстрее, чем на любом SSD-диск. По этой причине мы рекомендуем хранить как можно больше рабочих данных в памяти (мы предполагаем, что вы, конечно, используете InnoDB). Также по этой причине вы не хотите использовать Swap для MySQL, но не забывайте, что медленный MySQL всегда лучше, чем вообще никакой MySQL, поэтому не забудьте настроить раздел Swap, но старайтесь избегать его использования. Фактически, мы видели, как многие люди просто удаляли раздел подкачки … а затем OOM Killer сделал свою работу … и mysqld часто становится его первой жертвой. MySQL выделяет буферы и кэши для повышения производительности операций с базой данных. Этот процесс подробно описан в руководстве, В этой серии статей мы предоставляем вам некоторую информацию, чтобы проверить потребление памяти MySQL и какие настройки или действия конфигурации могут быть сделаны, чтобы понять и контролировать использование памяти MySQL. Мы начнем серию с операционной системы.
На уровне ОС есть несколько команд, которые мы можем использовать, чтобы понять использование памяти MySQL.
Вы можете проверить mysqld использование памяти из командной строки:
# ps -eo size,pid,user,command --sort -size | grep [m]ysqld \ | awk '{ hr=$1/1024 ; printf("%13.2f Mb ",hr) } { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }' \ |cut -d "" -f2 | cut -d "-" -f1
Вывод:
1841.10 Mb /usr/sbin/mysqld 0.46 Mb /bin/sh /usr/bin/mysqld_safe
top также может быть использован для проверки этого. Для top 3.2:
# top -ba -n1 -p $(pidof mysqld) | grep PID -A 1
Вывод:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1752 mysql 20 0 1943m 664m 15m S 0.0 11.1 19:55.13 mysqld # top -ba -n1 -m -p $(pidof mysqld) | grep PID -A 1
Вывод:
PID USER PR NI USED RES SHR S %CPU %MEM TIME+ COMMAND 1752 mysql 20 0 664m 664m 15m S 2.0 11.1 19:55.17 mysqld
Для более поздней вершины вы можете использовать top -b -o %MEM -n1 -p $(pidof mysqld) | grep PID -A 1 VIRT, представляющий общий объем виртуальной памяти, используемой mysql. Он включает в себя весь код, данные и общие библиотеки, а также страницы, которые в конечном итоге были заменены. USED сообщает сумму rss процесса (размер резидентного набора, часть памяти, занятую процессом, который содержится в оперативной памяти) и общее количество подкачки. Позже мы увидим, что мы можем проверить из клиента MySQL.
Итак, мы видим, что это может в конечном итоге включать и измененные страницы. Давайте проверим, использует ли mysqld подкачку, и первое, что нужно сделать, это проверить, есть ли у машины некоторая информация в swap:
# free -m
Вывод:
total used free shared buffers cached Mem: 5965 4433 1532 128 454 2359 -/+ buffers/cache: 1619 4346 Swap: 2045 30 2015
Мы видим, что используется небольшое количество подкачки (30 МБ), это MySQL? Давайте проверим:
# cat /proc/$(pidof mysqld)/status | grep Swap
Вывод:
VmSwap: 0 kB
Отлично, mysqld не используется. Если вы действительно хотите узнать, какие процессы поменялись местами, выполните следующую команду:
for i in $(ls -d /proc/[0-9]*) do out=$(grep Swap $i/status 2>/dev/null) if [ "x$(echo $out | awk '{print $2}')" != "x0" ] && [ "x$(echo $out | awk '{print $2}')" != "x" ] then echo "$(ps -p $(echo $i | cut -d'/' -f3) \ | tail -n 1 | awk '{print $4'}): $(echo $out | awk '{print $2 $3}')" fi done
Конечно, страницы в разделе подкачки могли существовать уже давно и никогда не использовались, поскольку… конечно, мы рекомендуем использовать vmstat и проверять столбцы si и т. д. (Настоятельно рекомендуется использовать систему трендов):
# vmstat 1 10
Вывод:
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 162280 120352 1344112 0 0 1035 197 584 637 19 5 75 1 1 0 0 0 162068 120484 1344256 0 0 136 4 1346 804 1 0 97 0 1 0 0 0 162180 120484 1344260 0 0 0 4 1572 733 0 1 98 0 1 2 0 0 148280 123580 1351640 0 0 10208 4 2553 2091 21 3 70 5 1 3 0 0 126864 125400 1363440 0 0 12164 316 3624 4652 54 9 24 11 3 0 0 0 135020 126188 1368308 0 0 4632 856 3407 4793 53 12 30 3 3 0 0 0 134740 126328 1368388 0 0 132 40 1514 849 1 0 98 0 1 1 0 0 107908 126388 1368360 0 0 4 2220 2093 1854 24 8 66 0 2 1 1 0 115552 126436 1368536 0 0 148 212 2074 1798 26 5 67 0 1 1 0 0 250776 126440 1368536 0 0 44 4 2202 1573 24 10 66 0 1
На этом сервере мы можем видеть, что mysqld подкачку не использует, но если бы это было так, и некоторое свободное ОЗУ оставалось доступным, что можно было бы сделать? Если это так, вы должны проверить 2 прямые причины:
Параметр swappiness контролирует стремление ядра перемещать процессы из физической памяти и помещать их в раздел подкачки. Как мы объяснили ранее, диски намного медленнее, чем ОЗУ, поэтому это приводит к более медленному времени отклика для системы и приложений, если процессы слишком агрессивно перемещаются из памяти. Высокое значение подкачки означает, что ядро будет более склонно к отмене сопоставления страниц. Низкое значение swappiness означает обратное, ядро будет менее склонно к распаковке отображенных страниц. Это означает, что чем выше значение swappiness, тем больше будет система подкачки! Значение по умолчанию (60) слишком велико для выделенного сервера MySQL и должно быть уменьшено. Обратите внимание, что с более старыми ядрами Linux (ранее 2.6.32), 0 означало, что ядро должно избегать выгрузки процессов из физической памяти как можно дольше. Теперь это же значение полностью исключает использование swap. Мы рекомендуем установить его на 1 или 5.
# sysctl -w vn.swappinness=1
Для серверов, имеющих несколько ядер NUMA, рекомендуется установить режим чередования NUMA, который уравновешивает распределение памяти для всех узлов. MySQL 8.0 поддерживает NUMA для InnoDB. Вам просто нужно включить его в своей конфигурации: innodb_numa_interleave = 1 чтобы проверить, есть ли у вас несколько узлов NUMA, вы можете использовать numactl -H. Это два разных вывода:
# numactl -H Вывод: available: 1 nodes (0) node 0 cpus: 0 1 2 3 4 5 6 7 node 0 size: 64379 MB node 0 free: 2637 MB node distances: node 0 0: 10 | # numactl -H Вывод: available: 4 nodes (0-3) node 0 cpus: 0 2 4 6 node 0 size: 8182 MB node 0 free: 221 MB node 1 cpus: 8 10 12 14 node 1 size: 8192 MB node 1 free: 49 MB node 2 cpus: 9 11 13 15 node 2 size: 8192 MB node 2 free: 4234 MB node 3 cpus: 1 3 5 7 node 3 size: 8192 MB node 3 free: 5454 MB node distances: node 0 1 2 3 0: 10 16 16 16 1: 16 10 16 16 2: 16 16 10 16 3: 16 16 16 10 |
Мы можем видеть, что при наличии нескольких узлов NUMA (правый столбец) по умолчанию, память распределяется неравномерно между всеми этими узлами. Это может привести к большему обмену.
Еще один момент, который мы можем проверить из ОС – это кеш файловой системы. По умолчанию Linux будет использовать кэш файловой системы для всех входов/выходов (это одна из причин, по которой использование MyISAM не рекомендуется, так как этот механизм хранения опирается на кэш FS и может привести к потере данных, так как Linux синхронизирует эти записи. каждые 10 секунд). Конечно, поскольку вы используете InnoDB, с O_DIRECT as innodb_flush_method, MySQL будет обходить кеш файловой системы (InnoDB уже имеет достаточно оптимизированных кэшей в любом случае, и один дополнительный не нужен). InnoDB не будет использовать кэш-память FS для файлов данных (* .ibd). Но, конечно, есть и другие файлы, используемые в MySQL, которые все еще будут использовать кэш FS. Давайте проверим этот пример:
# ~fred/dbsake fincore binlog.000017
Вывод:
binlog.000017: total_pages=120841 cached=50556 percent=41.84 # ls -lh binlog.000017
Вывод:
-rw-r----- 1 mysql mysql 473M May 30 22:56 binlog.000017 # free -m
Вывод:
total used free shared buffers cached Mem: 5965 4608 1356 128 435 2456 -/+ buffers/cache: 1716 4249 Swap: 2045 30 2015 # ~fred/dbsake uncache binlog.000017
Вывод:
Uncached binlog.000017 # free -m
Вывод:
total used free shared buffers cached Mem: 5965 4413 1552 128 435 2259 -/+ buffers/cache: 1718 4247 Swap: 2045 30 2015
Несколько объяснений. Мы начали проверять, сколько двоичных журналов присутствовало в кеше файловой системы (используя dbsake fincore), и мы увидели, что 42% из 473M использовали оперативную память в качестве кеша FS. Затем мы принудительно распаковали эти страницы в кеше (используя fincore uncache) и, наконец, вы могли видеть, что мы освободили +/- 195 МБ ОЗУ. Вы можете быть удивлены, увидев, какие журналы или файлы данных используют кэш FS (например, для создания файла). Мы настоятельно рекомендуем вам проверить это.