MySQL не освобождает память

8

Похоже, что MySQL хочет сохранить всю таблицу в кэше (размер таблицы = ~ 20 ГБ) после того, как на ней будут выполнены какие-либо большие операции вставки или операторы выбора. Прямо сейчас мой буферный пул innodb составляет 20 ГБ. Общий объем оперативной памяти составляет 32 ГБ. Я предоставлю некоторое использование памяти и вывод из состояния innodb, а также вывод из mysqltuner. Последние несколько дней это сводит меня с ума. Пожалуйста помоги! Я ценю любые отзывы и, пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

Кроме того, выполнение «FLUSH TABLES» просто закрывает и снова открывает их в памяти. По крайней мере, я думаю, что это то, что происходит. Вот текущее состояние памяти innodb, прежде чем я выполнил кучу вставок:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 21978152960; in additional pool allocated 0
Dictionary memory allocated 6006471
Buffer pool size   1310719
Free buffers       347984
Database pages     936740
Old database pages 345808
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 78031, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 551887, created 384853, written 4733512
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 936740, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

Процент использования памяти mysqld: 60,9%

Процент использования памяти mysqld после вставок (1 млн записей): 63,3%

а затем после дополнительных вставок (3 млн записей): 70,2%

разве это не должно составлять около 62,5% ? (20 / 32ГБ) всего оперативной памяти?

вывод сверху сортировки моего использования MEM:

top - 14:30:56 up 23:25,  3 users,  load average: 3.63, 2.31, 1.91
Tasks: 208 total,   4 running, 204 sleeping,   0 stopped,   0 zombie
Cpu(s): 96.0%us,  3.0%sy,  0.0%ni,  0.0%id,  1.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  28821396k total, 28609868k used,   211528k free,   138696k buffers
Swap: 33554428k total,    30256k used, 33524172k free,  1208184k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 1228 mysql     20   0 25.1g  19g 5512 S   31 70.2  62:01.10 mysqld

Вот вывод памяти innodb после выполнения этих вставок:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 21978152960; in additional pool allocated 0
Dictionary memory allocated 6006471
Buffer pool size   1310719
Free buffers       271419
Database pages     1011886
Old database pages 373510
Modified db pages  4262
Pending reads 1
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 82521, not young 0
7.08 youngs/s, 0.00 non-youngs/s
Pages read 585218, created 426667, written 5192189
24.08 reads/s, 53.08 creates/s, 1135.07 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1011886, unzip_LRU len: 0
I/O sum[0]:cur[266], unzip sum[0]:cur[0]

В соответствии с состоянием innodb, общая выделенная память одинакова, но моя ОС (Virtual Ubuntu Server 12.04) сообщает об использовании большего количества памяти. Использование памяти остается прежним, и здесь я определяю это как службу MySQL, не «освобождающую» память. Какие-либо предложения?

вывод из mysqltuner.pl:

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +ARCHIVE +BLACKHOLE +CSV -FEDERATED +InnoDB +MRG_MYISAM
[--] Data in MyISAM tables: 226M (Tables: 287)
[--] Data in InnoDB tables: 33G (Tables: 1000)
[--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 17)
[--] Data in MEMORY tables: 0B (Tables: 1)
[!!] Total fragmented tables: 959

-------- Security Recommendations  -------------------------------------------
[OK] All database users have passwords assigned

-------- Performance Metrics -------------------------------------------------
[--] Up for: 23h 14m 27s (1M q [14.603 qps], 6K conn, TX: 16B, RX: 1B)
[--] Reads / Writes: 46% / 54%
[--] Total buffers: 22.2G global + 2.7M per thread (151 max threads)
[OK] Maximum possible memory usage: 22.6G (82% of installed RAM)
[OK] Slow queries: 0% (6/1M)
[OK] Highest usage of available connections: 6% (10/151)
[OK] Key buffer size / total MyISAM indexes: 2.0G/58.7M
[OK] Key buffer hit rate: 100.0% (216M cached / 38K reads)
[OK] Query cache efficiency: 81.2% (799K cached / 984K selects)
[!!] Query cache prunes per day: 5561
[OK] Sorts requiring temporary tables: 4% (819 temp sorts / 16K sorts)
[!!] Temporary tables created on disk: 27% (6K on disk / 22K total)
[OK] Thread cache hit rate: 99% (11 created / 6K connections)
[!!] Table cache hit rate: 0% (97 open / 10K opened)
[OK] Open file limit used: 12% (129/1K)
[OK] Table locks acquired immediately: 99% (433K immediate / 433K locks)
[!!] InnoDB  buffer pool / data size: 20.0G/33.6G
[OK] InnoDB log waits: 0
-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    MySQL started within last 24 hours - recommendations may be inaccurate
    Enable the slow query log to troubleshoot bad queries
    When making adjustments, make tmp_table_size/max_heap_table_size equal
    Reduce your SELECT DISTINCT queries without LIMIT clauses
    Increase table_cache gradually to avoid file descriptor limits
    Read this before increasing table_cache over 64: http://bit.ly/1mi7c4C
Variables to adjust:
    query_cache_size (> 128M)
    tmp_table_size (> 128M)
    max_heap_table_size (> 16M)
    table_cache (> 431)
    innodb_buffer_pool_size (>= 33G)
Чернер
источник

Ответы:

8

Прежде всего, взгляните на архитектуру InnoDB (предоставлено Percona CTP Вадимом Ткаченко)

InnoDB Архитектура

InnoDB

Ваш статус для пула буферов говорит

Размер пула буферов 1310719

Это ваш размер буфера в страницах. Каждая страница 16K . Получается 20G - 16K.

Обратите внимание на следующее: вы поместили данные в буферный пул InnoDB. Что изменилось?

Buffer pool size   1310719 
Free buffers       271419 (It was 347984)
Database pages     1011886 (Is was 936740)
Old database pages 373510 (It was 345808)
Modified db pages  4262 (It was 0)

Также обратите внимание на разницу между размером пула буферов в страницах.

1310719 (размер пула буферов) - 1011886 (страницы базы данных) = 298833

Это 298833 страницы InnoDB. Сколько места это ???

mysql> select FORMAT(((1310719  - 1011886) * 16384) / power(1024,3),3) SpaceUsed;
+-----------+
| SpaceUsed |
+-----------+
| 4.560     |
+-----------+

Это 4,56 ГБ. Это пространство используется для секции вставки буфера пула буферов InnoDB (он же Change Buffer) . Это используется для смягчения изменений неуникальных индексов в файле системных табличных пространств (которые все стали называть ibdata1).

InnoDB Storage Engine управляет внутренними ресурсами пула буферов. Поэтому InnoDB никогда не превзойдет 62,5% оперативной памяти. Более того, ОЗУ для пула буферов никогда не возвращается.

ГДЕ 70,2% оперативной памяти приходит ???

Оглянись на вывод mysqltuner.plэтих строк

[OK] Maximum possible memory usage: 22.6G (82% of installed RAM)
Key buffer size / total MyISAM indexes: 2.0G/58.7M
[--] Total buffers: 22.2G global + 2.7M per thread (151 max threads)

У mysqld есть три основных способа выделения оперативной памяти

  • Вы устанавливаете 20G пула буферов InnoDB
  • У вас есть 2G для MyISAM Key Cache
  • Оставшиеся 0,6 ГБ получены из 151 ( max_connections ) раз (2,7 МБ на соединение с БД или потоком). 2.7M происходит от ( join_buffer_size + sort_buffer_size + read_buffer_size )

Любой небольшой всплеск подключений к БД увеличит ОЗУ выше порога 62,5%, который вы видите для InnoDB.

MyISAM (примечание стороны)

Что бросается в глаза

Key buffer size / total MyISAM indexes: 2.0G/58.7M

Так как у вас так мало индексов для MyISAM. Вы можете установить key_buffer_size на 64M.

Вам не нужно перезапускать MySQL для этого. Просто беги

SET GLOBAL ket_buffer_size = 1024 * 1024 * 64;

Затем измените это в my.cnf

[mysqld]
key_Buffer_size = 64M

Это даст ОС 2 ГБ оперативной памяти. Ваша виртуальная машина будет просто любить вас за это !!!

Попробуйте!

ПРЕДОСТЕРЕЖЕНИЕ

Работа FLUSH TABLESс таблицами InnoDB просто закрывает файлы от .ibdфайлов. Это не будет толкать изменения напрямую. Изменения должны перенести свой путь через каналы InnoDB. Вот почему вы видите всплеск Modified db pages. 4262 измененных страниц (66,59 МБ) сбрасываются, когда InnoDB не планирует их сброс.

RolandoMySQLDBA
источник
Большое спасибо за глубокий анализ. Теперь это имеет гораздо больше смысла - так ли это, что буферный пул innodb будет оставаться с максимальной загрузкой памяти (20 ГБ)? И общая память, которую mysqld когда-либо будет использовать, составляет 82% ??
Чернер
Это да на оба вопроса
RolandoMySQLDBA
@RolandoMySQLDBA, если я правильно понимаю, MySQL не освобождает память, и это то, что это. Нет?
Малус Ян
1
@MalusJan Мой ответ не об освобождении памяти. Мой ответ касается того, сколько ОЗУ используется для StorageEngines и подключений к БД. Время от времени устаревшие соединения с БД, которые не закрыты должным образом, могут удерживать выделенную ОЗУ. Кэши для буферов Storage Engine могут динамически изменяться для MyISAM (MySQL 5.x +) и InnoDB (MySQL 5.7+). Кэши для соединений с БД можно динамически изменять для новых входящих соединений (но не для открытых в данный момент). Память не освобождается из-за ошибок утечки памяти в mysqld.
RolandoMySQLDBA
@RolandoMySQLDBA. На сервере у нас более 10 баз данных, и нам нужно создавать дампы каждый день, и каждая из них mysqldumpзанимает немного памяти, а не освобождает их. Так что после всего дампа у нас около 80% оперативной памяти занято процессом mysql. У вас есть какое-то решение для этого? Спасибо
Малус Ян
0

Я столкнулся с подобной проблемой. Вопрос: вы используете разделенную конфигурацию памяти? (THP и расшаренный) Если да, то отключите огромные страницы и позвольте MySQL управлять памятью и следить за ней. Также проверьте, сколько параллельных процессов запущено на сервере, включая процессы в спящем режиме. Если вы используете конфигурацию с общей памятью, вам нужно больше памяти для этого сервера.

Раджа Навид
источник