萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL「Out of memory (Needed 76016 bytes)」記憶體配置災難現場還原

錯誤現場

Out of memory (Needed 76016 bytes)

伺服器實體記憶體 **3 GB**,但配置檔參數驚人:

key_buffer_size = 1294963200        # ~1.2 GB
read_buffer_size = 2147479552       # ~2 GB  (每連線!)
sort_buffer_size = 2294967295       # ~2.1 GB(每連線!)
max_connections = 1000
# 理論峰值記憶體 = key_buffer + (read_buffer + sort_buffer) × max_connections
# ≈ 1.2G + (2G + 2.1G) × 1000 = 4.1 TB  →  直接 OOM

記憶體估算公式

總記憶體 ≈
  全域緩衝區
  + (每連線緩衝區總和) × max_connections

全域緩衝區 = key_buffer_size + innodb_buffer_pool_size + query_cache_size + ...
每連線緩衝區 = read_buffer_size + read_rnd_buffer_size + sort_buffer_size + join_buffer_size + thread_stack + ...

立即修正配置(3 GB 記憶體適用)

[mysqld]
# 全域
innodb_buffer_pool_size = 1G          # 60% 給 InnoDB
key_buffer_size = 64M                 # MyISAM 極小或不用
query_cache_size = 0                  # 關閉 QC,避免鎖爭用
table_open_cache = 2000

# 每連線(保守值,1000 連線總計 ~1.5G)
sort_buffer_size = 2M
read_buffer_size = 1M
read_rnd_buffer_size = 4M
join_buffer_size = 2M
thread_stack = 256K

# 連線控制
max_connections = 300                 # 降低上限,配合應用連線池
thread_cache_size = 64
wait_timeout = 300

# 其它
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT

PHP 端配合調整

; php.ini
max_execution_time = 120
max_input_time = 60
memory_limit = 128M          ; 視腳本複雜度調整,避免單腳本佔滿記憶體

修改後 systemctl restart php-fpm(或 Apache / IIS)。

驗證記憶體佔用

# 重啟 MySQL 後
ps aux | grep mysqld
# 觀察 RSS/RES 是否在 2.5G 以內

# 連線壓力測試
sysbench oltp_read_write --mysql-user=root --mysql-password=xxx --tables=10 --table-size=10000 --threads=200 --time=60 run

教訓總結

  • 「每連線」參數乘以 max_connections 是記憶體殺手,預設值通常已足夠,切勿盲目調大。
  • 全域參數優先調大(innodb_buffer_pool_size),每連線參數保守設定。
  • 上線前必跑壓測,觀察實際 RSS 與 OOM Killer 紀錄(dmesg | grep -i oom)。
copyright © 萬盛學電腦網 all rights reserved