目錄標題
- **一、問題現象**
- **二、核心排查步驟**
- **1. 參數檢查**
- **2. 內存使用分析**
- **3. 存儲過程/函數/視圖檢查**
- **4. 操作系統級檢查**
- **三、解決方案**
- **1. 調整MySQL配置**
- **2. 關閉透明大頁(THP)**
- **3. 優化查詢與存儲過程**
- **4. 硬件與環境優化**
- **四、總結**
MySQL內存使用率高問題排查與解決方案:
一、問題現象
- 內存占用異常:通過
top
命令發現MySQL進程(mysqld
)占用了90.7%的物理內存(56.5G/62G)。 - 系統負載:CPU使用率較低(1.3%),但內存幾乎耗盡。
二、核心排查步驟
1. 參數檢查
- MySQL版本:8.0.39(未開啟慢查詢日志)。
- 關鍵內存參數:
SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; -- 12G(配置較低,建議調整為總內存的70%~80%) SHOW VARIABLES LIKE 'tmp_table_size'; -- 16M(臨時表內存限制過小)
- 臨時文件路徑:
/tmp
(建議改為專用目錄以避免性能問題)。
2. 內存使用分析
-
全局內存統計:
SELECT SUM(CAST(replace(current_alloc,'MiB','') AS DECIMAL(10,2))) FROM sys.memory_global_by_current_bytes WHERE current_alloc LIKE '%MiB%';
結果:總內存使用約1933.69MB。
-
分事件內存占用:
SELECT event_name, sys.format_bytes(CURRENT_NUMBER_OF_BYTES_USED) FROM performance_schema.memory_summary_global_by_event_name ORDER BY CURRENT_NUMBER_OF_BYTES_USED DESC LIMIT 10;
關鍵發現:
memory/innodb/buf_buf_pool
占用13.29GB(InnoDB緩沖池)。memory/group_rpl/Gcs_xcom::xcom_cache
占用1024MB(復制相關緩存)。
-
用戶級內存統計:
SELECT user, event_name, current_number_of_bytes_used/1024/1024 AS MB_USED FROM performance_schema.memory_summary_by_account_by_event_name WHERE host <> "localhost" ORDER BY MB_USED DESC LIMIT 10;
發現:特定用戶(如
zqzh
)在memory/temptable/physical_ram
中占用65MB。
3. 存儲過程/函數/視圖檢查
-
存儲過程與函數:
SELECT Routine_schema, Routine_type FROM information_schema.Routines WHERE Routine_schema NOT IN ('mysql','information_schema','performance_schema','sys');
結果:多個業務庫存在大量存儲過程和函數(如
bpc
、bsc
等)。 -
視圖與觸發器:
SELECT TABLE_SCHEMA, COUNT(TABLE_NAME) FROM information_schema.VIEWS; SELECT TRIGGER_SCHEMA, COUNT(*) FROM information_schema.triggers;
結果:視圖和觸發器數量較少,非主要內存消耗源。
4. 操作系統級檢查
-
進程內存占用:
ps -eo user,pid,vsz,rss | grep mysqld
結果:
mysqld
進程虛擬內存(VIRT)96.2G,物理內存(RES)56.5G。 -
內存映射分析:
pmap -d <mysql_pid> | tail -1
關鍵指標:
writeable/private
:進程實際占用的私有內存(持續增長可能提示內存泄漏)。
-
透明大頁(THP)檢查:
cat /sys/kernel/mm/transparent_hugepage/enabled
結果:THP處于開啟狀態(可能導致內存分配效率低下)。
三、解決方案
1. 調整MySQL配置
- 增加InnoDB緩沖池:
innodb_buffer_pool_size = 48G -- 根據總內存(62G)調整為77%
- 優化臨時表內存:
tmp_table_size = 256M max_heap_table_size = 256M
2. 關閉透明大頁(THP)
- 臨時關閉:
echo never > /sys/kernel/mm/transparent_hugepage/enabled echo never > /sys/kernel/mm/transparent_hugepage/defrag
- 永久關閉:
在/etc/rc.local
中添加:if test -f /sys/kernel/mm/transparent_hugepage/enabled; thenecho never > /sys/kernel/mm/transparent_hugepage/enabled fi if test -f /sys/kernel/mm/transparent_hugepage/defrag; thenecho never > /sys/kernel/mm/transparent_hugepage/defrag fi
3. 優化查詢與存儲過程
- 分析慢查詢:開啟慢查詢日志,定位低效SQL。
- 減少存儲過程依賴:將復雜邏輯移至應用層,避免存儲過程內存泄漏。
4. 硬件與環境優化
- 增加物理內存:若業務需求增長,考慮升級服務器內存。
- 遷移臨時文件目錄:將
tmpdir
設置為專用高速存儲路徑。
四、總結
- 核心問題:MySQL內存使用率高主要由InnoDB緩沖池配置不足、THP機制效率低下及存儲過程/函數內存占用引起。
- 解決重點:調整緩沖池大小、關閉THP、優化查詢邏輯。
- 后續監控:通過
sys.memory_global_by_current_bytes
和pmap
持續觀察內存變化。
通過以上步驟,可顯著降低MySQL內存占用并提升穩定性。