首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL「文件未找到」錯誤 (errno 23/24) 根因與三種解決方案

     編輯:MySQL 資料庫相關知識

報錯 ERROR '...' not found (errno: 23) 或 Can't open file: ... (errno: 24),本質是 **MySQL 進程打開文件描述符不足**。本文從內核限制、MySQL 參數、架構優化三個維度給出完整解決路徑。

錯誤碼含義

$ perror 23
Error code 23: File table overflow
$ perror 24
Error code 24: Too many open files
$ perror 11
Error code 11: Resource temporarily unavailable

根因分析

  • MySQL 每張表打開需消耗 **3 個文件描述符**(.frm、.MYD、.MYI 或 .ibd)。
  • 高併發下,table_open_cache × 3 + max_connections × (線程棧 + 臨時文件) 易突破系統限制。
  • 默認 ulimit -n 1024 極小,生產環境嚴重不足。

方案一:調大系統級文件描述符限制(根治)

臨時生效(當前 Shell)

ulimit -n 65535

永久生效(需 root)

# /etc/security/limits.conf
mysql soft nofile 65535
mysql hard nofile 65535

# /etc/systemd/system/mysqld.service.d/override.conf (systemd)
[Service]
LimitNOFILE=65535

驗證

cat /proc/$(pidof mysqld)/limits | grep "Max open files"

方案二:調優 MySQL 參數減少佔用

注意:open_files_limit 僅是 MySQL 向 OS 申請的目標值,**最終上限仍由系統 ulimit 決定**。

方案三:架構層面減少表數量

  • 合併同結構表:如日誌表按月分表 → 改用分區表(PARTITION BY RANGE),元數據僅 1 條。
  • 避免過度分庫分表:中小應用單庫單表 + 索引優化往往足夠。
  • 定期清理臨時表:SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables'; 監控磁盤臨時表創建率。

排查清單

  1. SHOW GLOBAL STATUS LIKE 'Open%'; → Open_tables、Opened_tables、Open_files。
  2. SHOW VARIABLES LIKE 'open_files_limit'; 對比 ulimit -n。
  3. cat /proc/$(pidof mysqld)/limits 確認進程實際限制。
  4. 若為容器環境(Docker/K8s),需在宿主機或 Pod `securityContext` 設定 ulimit。

總結

  1. **首選方案一**:系統級 ulimit -n 65535 + systemd LimitNOFILE,一勞永逸。
  2. **輔助方案二**:合理設定 table_open_cache、max_connections,避免過度緩存。
  3. **長期方案三**:分區表替代手動分表,從源頭減少文件數。

文件描述符耗盡是 MySQL 高併發下的「隱形殺手」,建議**新建實例即納入基線配置**,而非等報錯再救火。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
參數建議值影響
table_open_cache2000~10000 (視表數量)減少打開/關閉表頻率,但增加持有描述符數
table_definition_cache1400~4000緩存 .frm 定義,減少元數據讀取
max_connections實際峰值 + 20%每連接消耗線程棧、網絡緩衝、臨時文件描述符
open_files_limit65535 (MySQL 內部提示)啟動時向 OS 申請,受 ulimit 硬限制約束