MySQL não liberando memória

8

O MySQL parece querer manter uma tabela inteira no cache (tamanho da tabela = ~ 20 GB) após a inserção de grandes inserções ou instruções de seleção. No momento, meu buffer pool do innodb é de 20 GB. A RAM total é de 32 GB. Fornecerei algum uso de memória e saída do status innodb, bem como saída do mysqltuner. Isso está me deixando louco nos últimos dias. Por favor ajude! Agradeço qualquer feedback e entre em contato se precisar de mais informações.

Além disso, a execução de 'FLUSH TABLES' apenas as fecha e as reabre na memória. Pelo menos eu acho que é isso que está acontecendo. Aqui está o status atual da memória do innodb antes de executar várias inserções:

----------------------
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]

porcentagem de uso da memória no mysqld: 60,9%

porcentagem de uso da memória mysqld após inserções (1 milhão de registros): 63,3%

e depois de mais inserções (3 mil registros): 70,2%

não deveria atingir 62,5% ? (20 / 32GB) ram total?

saída da parte superior classificando meu uso de 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

aqui está a saída de memória innodb após a execução dessas inserções:

----------------------
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]

De acordo com o status innodb, a memória total alocada é a mesma - mas meu sistema operacional (Virtual Ubuntu Server 12.04) está relatando mais uso de memória que isso. O uso da memória permanece o mesmo e aqui estou definindo-o como o serviço MySQL que não 'libera' a memória. Alguma sugestão?

saída do 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)
Cherner
fonte

Respostas:

8

Primeiro, dê uma olhada na arquitetura InnoDB (cortesia de Percona CTP Vadim Tkachenko)

Arquitetura InnoDB

InnoDB

Seu status para o Buffer Pool diz

Tamanho do buffer pool 1310719

Esse é o seu tamanho do buffer em páginas. Cada página tem 16K . Isso acontece 20G - 16K.

Observe o seguinte: Você inseriu dados no pool de buffer do InnoDB. O que mudou ?

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)

Além disso, observe a diferença entre o tamanho do buffer pool em páginas.

1310719 (tamanho do buffer pool) - 1011886 (páginas do banco de dados) = 298833

São 298833 páginas do InnoDB. Quanto espaço é esse ???

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

Isso é 4,56GB. Esse espaço é usado para a seção Buffer de inserção do InnoDB Buffer Pool (também conhecido como Change Buffer) . Isso é usado para atenuar alterações em índices não únicos no arquivo de espaço de tabela do sistema (que todos passaram a conhecer como ibdata1).

O InnoDB Storage Engine está gerenciando os componentes internos do buffer pool. Portanto, o InnoDB nunca ultrapassará 62,5% da RAM. Além disso, a RAM do Buffer Pool nunca é devolvida.

ONDE ESTÃO OS 70,2% DE RAM VINDO ???

Olhe para a saída mysqltuner.pldessas linhas

[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)

O mysqld possui três maneiras principais de alocar RAM

Qualquer pequeno pico no DB Connections aumentará a RAM além do limite de 62,5% que você vê no InnoDB.

MyISAM (Nota lateral)

O que chama minha atenção é

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

Como você tem tão poucos índices para o MyISAM. Você pode definir o key_buffer_size para 64M.

Você não precisa reiniciar o mysql para isso. Apenas corra

SET GLOBAL ket_buffer_size = 1024 * 1024 * 64;

Em seguida, modifique isso em my.cnf

[mysqld]
key_Buffer_size = 64M

Isso dará ao sistema operacional 2 GB de RAM. Sua VM simplesmente o amará por isso !!!

De uma chance !!!

EMBARGO

A execução FLUSH TABLESem tabelas do InnoDB simplesmente fecha os .ibdarquivos. Isso realmente não fará alterações diretamente. As mudanças precisam migrar através dos canais do InnoDB. É por isso que você vê o pico Modified db pages. As 4262 páginas alteradas (66,59 MB) são liberadas quando o InnoDB agendar sua liberação.

RolandoMySQLDBA
fonte
muito obrigado pela análise aprofundada. Faz muito mais sentido agora - então é verdade que o buffer pool do innodb permanecerá no uso máximo de memória ao longo do tempo (20 GB)? E a memória total que o mysqld usará é de 82%?
284 Cherner
Isso é um sim para ambas as perguntas #
RolandoMySQLDBA
@RolandoMySQLDBA, Se bem entendi, o MySQL não libera a memória e é isso que é. Não?
Malus Jan
11
@ MalusJan Minha resposta não é sobre a memória sendo liberada. Minha resposta aborda a quantidade de RAM usada para StorageEngines e DB Connections. Às vezes, as conexões de banco de dados remanescentes não fechadas corretamente podem conter a RAM alocada. Os caches dos buffers do Storage Engine podem ser redimensionados dinamicamente para MyISAM (MySQL 5.x +) e InnoDB (MySQL 5.7+). Os caches para conexões de banco de dados podem ser redimensionados dinamicamente para novas conexões de entrada (não conexões abertas no momento). A memória não liberada é devido a erros de vazamento de memória no mysqld.
RolandoMySQLDBA
@RolandoMySQLDBA. No servidor, temos mais de 10 bancos de dados e precisamos criar dump todos os dias e cada mysqldumpum deles precisa de memória e não os libera. Então, depois de todo o despejo, temos cerca de 80% da memória RAM ocupada pelo processo mysql. Você tem alguma solução para isso? Thanks
Malus Jan
0

Eu enfrentei um tipo semelhante de problema. Pergunta: você está usando a configuração de memória dividida? (THP e compartilhado) Se sim, desative enormes páginas e deixe o MySQL manipular a memória e continuar monitorando. Verifique também quantos processos paralelos em execução no servidor, incluindo processos no modo de suspensão. Se você estiver usando a configuração de memória compartilhada, precisará de mais memória para este servidor.

Raja Naveed
fonte