MySQL不释放内存


8

在对它执行任何大的插入或选择语句之后,MySQL似乎想将整个表保留在缓存中(表大小=〜20GB)。现在我的innodb缓冲池是20GB。总内存为32GB。我将提供一些内存使用情况以及innodb状态的输出以及mysqltuner的输出。过去几天一直让我发疯。请帮忙!感谢您提供任何反馈意见,如果您需要更多信息,请告诉我。

同样,执行“刷新表”只会关闭并在内存中重新打开它们。至少我认为这是正在发生的事情。这是我执行一堆插入操作之前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插入后的内存使用百分比(百万记录):63.3%

然后再插入(300万条记录):70.2%

它不应该限制在62.5%左右吗?(20 / 32GB)总内存?

排序我的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)

Answers:


8

首先,我们来看一下InnoDB架构(由Percona CTP Vadim Tkachenko提供)

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.56GB。该空间用于InnoDB缓冲池(又名更改缓冲区)Insert Buffer部分。这用于减轻对系统表空间文件中非唯一索引的更改(所有更改都称为ibdata1)。

InnoDB存储引擎正在管理缓冲池的内部。因此,InnoDB永远不会超过RAM的62.5%。而且,缓冲池的RAM永远不会退回。

70.2%的RAM来自哪里?

回头看看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有三种主要的分配RAM的方式

数据库连接中的任何小峰值都会使RAM超出您对InnoDB看到的62.5%的阈值。

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

这将为操作系统提供2GB的RAM。您的VM只会为此而爱您!

试试看 !!!

警告

FLUSH TABLES在InnoDB表上运行只会针对.ibd文件关闭文件。这不会真正直接推动更改。这些更改必须通过InnoDB的管道进行迁移。这就是为什么您看到的峰值Modified db pages。当InnoDB计划其刷新时,将刷新4262个更改的页面(66.59 MB)。


非常感谢您进行深入分析。现在,它变得更有意义了-的确,innodb缓冲池将在一段时间内保持最大内存使用率(20GB)吗?mysqld将使用的总内存为82%?
cherner 2014年

这两个问题都是肯定的
RolandoMySQLDBA 2014年

@RolandoMySQLDBA,如果我理解正确,MySQL不会释放内存,这就是事实。没有?
Malus 1

1
@MalusJan我的回答不是关于释放内存。我的答案是针对StorageEngines和DB Connections使用了多少RAM。有时,缠结不佳的数据库连接可能会占用已分配的RAM。可以为MyISAM(MySQL 5.x +)和InnoDB(MySQL 5.7+)动态调整存储引擎缓冲区的缓存大小。可以为新的传入连接(不是当前打开的连接)动态调整数据库连接的缓存大小。内存未释放是由于mysqld中的内存泄漏错误。
RolandoMySQLDBA

@RolandoMySQLDBA。在服务器上,我们有10多个数据库,我们需要每天创建转储,每个数据库都mysqldump占用一些内存而不释放它们。因此,在所有转储之后,我们大约有80%的ram被mysql进程占用。您对此有什么解决方案吗?谢谢
Malus 1

0

我曾经遇到过类似的问题。问题:您是否正在使用拆分内存配置?(THP和共享)如果是,则禁用大页面,并让MySQL处理内存并继续对其进行监视。还要检查服务器上正在运行多少个并行进程,包括处于睡眠模式的进程。如果使用共享内存配置,则此服务器需要更多内存。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.