MySQL記憶體使用過多,可能什麼原因?


轉自 MYSQL數據庫聯盟
去年,在【DBA驛站】中,收集到一位星友去某互聯網大廠面試的真題,其中有這樣一道面試題:線上有沒有遇到MySQL伺服器因為內存使用過大而OOM的情況,如果有說一下原因(面試官提示:MySQL運行時間很長,記憶體佔用會越來越大)當時給了一個解析,最近看了追風老師的專欄《一線DBA資料庫實戰經典案例30講》第5節:MySQL內存居高不下如何破局?
感覺當時對於這個面試題的解析還是不太完整的,這篇文章就來重新寫一下解析。 1 MySQL服務哪些部分會使用記憶體主要有Server層和InnoDB層。
1.1 Server層包括:Join buffer;Sort buffer;Query Cache(如果開啟);執行緒​​和連線。
1.2 InnoDB層主要包括:InnoDB Buffer Pool。而在Linux中,小於128k的內存,分片之後再釋放,並不會馬上歸還給OS。
大於128k的內存,使用後釋放,會馬上歸還給OS。
InnoDB Buffer Pool在MySQL啟動時申請的是虛擬內存,隨著資料量加載到內存中buffer pool慢慢申請實體內存,直到達到buffer設定上限。
如果沒達到上限,此時資料量小於設定的buffer大小,效能無疑是最好的,如果達到上限了,則會進行lru淘汰。
另外,如果調低buffer pool大小,你能發現free -g立刻看到free列立刻增大,這就是直接釋放給作業系統。
所以,如果InnoDB Buffer Pool設定合理,MySQL使用記憶體又遠遠超越InnoDB Buffer Pool設定的值,那就不是Buffer Pool的問題了。
2 分析MySQL記憶體使用情況可以透過啟用 performance_schema 中與記憶體相關的監控來查看 MySQL 的記憶體使用量。
開啟方式如下:

update performance_schema.setup_instruments set enabled = ‘yes’ where name like ‘memory/%’;

根據主機分組的記憶體使用:

select host,current_count_used/1024/1024 as used_MB ,current_allocated/1024/1024 as allocated_MB,current_avg_alloc/1024/1024 as avg_alloc_MB,current_max_alloc/1024/1024 as max_alloc_MB,total_allocated/1024/1024 as total_all_MB from sys.x$memory_by_host_by_current_bytes limit 5;

根據線程和事件分組的記憶體使用:

select * from performance_schema.memory_summary_by_thread_by_event_name limit 5;

某條SQL佔用的記憶體使用量:

select t.processlist_id,concat(t.PROCESSLIST_USER,’@’,t.PROCESSLIST_host) as account,m.event_name, m.CURRENT_NUMBER_OF_BYTES_USED/1024/1024/1024 as mem_used, t.PROCESSLIST_INFO from performance_schema.memory_summary_by_thread_by_event_name m, performance_schema.threads t where m.thread_id = t.thread_id and processlist_id is not null order by CURRENT_NUMBER_OF_BYTES_USED desc limit 5;

3 MySQL内存使用过多不释放的常见原因

内存泄漏和碎片:在 MySQL 长时间运行时,内存使用可能会逐渐增加,特别是在 Server 层。例如,performance_schema 中的 table_handles 表会占用大量内存(约 9GB),参考Bug:
https://bugs.mysql.com/bug.php?id=95504

配置问题:InnoDB Buffer Pool 、join_buffer_size、sort_buffer_size、query cache配置不合理。

内存分配器:MySQL默认使用的是glibc 内存分配器,glibc内存分配器的性能相较于jemalloc,内存分配和回收方面会弱一些,因此,推荐的是更换内存分配器为jemalloc方式。