解決 XAMPP MariaDB 遇到 errno 11「Resource temporarily unavailable」錯誤

Ubuntu 的 MariaDB 遇到 errno 11「Can't create a new thread」錯誤。問題不在記憶體,透過調整資料庫伺服器的 open_files_limit 限制解決。

Photo by Markus Spiske on StockSnap


問題狀況

在 Ubuntu 上執行的程式碼執行到一半,突然重複出現一樣的錯誤訊息:

Can't create a new thread (errno 11 "Resource temporarily unavailable")

與耗盡電腦記憶體而無法使用電腦的錯誤狀況不一樣。恢復原本中斷的程式碼,可以短暫執行,但過不久又遇到同樣錯誤。

調查問題狀況

1. 錯誤代碼 errno 11 "Resource temporarily unavailable" 是什麼意思?

errno 11 對應的是問題描述「資源暫時無法取得」[1]。MariaDB 呼叫建立新執行緒時,作業系統因為 file descriptor (檔案描述符) 耗盡,而回傳這個錯誤。

Linux/Unix 上每次網路連線、每張開啟的資料表、或開啟的每個 log 檔案,都需要消耗一個 file descriptor。當 open_files_limit 太低,連線一多就直接超出限制 [2][3]。

2.  file descriptor (檔案描述符) 目前限制是多少?

先確認目前有哪些相關 process 在執行:

ps aux | grep mysqld

輸出結果:

root   5247  ...  /bin/sh /opt/lampp/bin/mysqld_safe ...

mysql  5404  ...  /opt/lampp/sbin/mysqld ...

輸出結果顯示程序編號 (PID) 各自對應的執行程序,上方結果顯示 (1) PID 5247 是 mysqld_safe(wrapper script),(2) PID 5404 才是真正的 mysqld 主程序。

確認 PID 之後,再查各自程序的資源限制:

for pid in $(pgrep mysqld); do

    echo "=== PID $pid ==="

    cat /proc/$pid/limits | grep -E "open files|processes"

done

指令的結果是:

=== PID 5247 ===   ← mysqld_safe

Max open files    1024    1048576    files

=== PID 5404 ===   ← mysqld 主程序

Max open files    6590    6590       files

mysqld_safe 跟 mysqld 主程序是不同的程序。MySQL 和 MariaDB 官方文件說明 mysqld_safe 是 Unix 上啟動 mysqld server 的建議方式 [4][5]:

mysqld_safe 是在 Unix 系統上啟動 mysqld 伺服器的建議方式。mysqld_safe 會加入一些安全機制,例如在伺服器發生錯誤時自動重新啟動,以及將執行時資訊記錄到錯誤日誌中。

/proc/$pid/limits 的三個欄位

Limit              Soft Limit   Hard Limit   Units

Max open files     6590         6590         files

(1) Soft Limit 程序目前實際使用的限制

(2) Hard Limit 程序最多可以把 Soft Limit 調高到多少

(3) Units 單位

問題就在這裡:一開始 mysqld_safe(PID 5247)的軟限制 (Soft Limit) 是 1024,但接下來執行的 mysqld 主程序(PID 5404)拿到的卻是 6590,而且軟硬限制 (Hard Limit) 都被鎖死。

問題解決方式

因為不是一般安裝資料庫伺服器的方式,也就無法透過 systemd 管理 MariaDB 服務 [6][7]。使用 XAMPP 的資料庫伺服器,則是修改 XAMPP 的資料庫伺服器的設定檔:

1. 修改 XAMPP 的資料庫伺服器的設定檔
sudo nano /opt/lampp/etc/my.cnf
在 [mysqld] 區塊加入:
[mysqld]
open_files_limit  = 65535
2. 重啟 XAMPP 服務
sudo /opt/lampp/lampp stop
sudo /opt/lampp/lampp start
3. 確認生效
for pid in $(pgrep mysqld); do
    echo "=== PID $pid ==="
    cat /proc/$pid/limits | grep "open files"
done
兩個 process 都應該顯示:
Max open files    65535    65535    files

進入 MariaDB 做最終確認:
SHOW VARIABLES LIKE 'open_files_limit';
-- 應顯示 65535

因為是測試開發環境,所以調整 65535。如果是正式環境,可以搭配 MySQLTuner-perl 調整資料庫伺服器設定。

使用環境版本

1. OS: Ubuntu 24.04 LTS

2. XAMPP 8.2.x(Apache 2.4.58)

3. MariaDB 10.4.32

參考資料

  1. Linux Error Number Table (errno) https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/errnos/
  2. MySQL :: MySQL 8.0 Reference Manual :: B.3.2.16 File Not Found and Similar Errors https://dev.mysql.com/doc/refman/8.0/en/not-enough-file-handles.html
  3. A Mystery with MySQL open_files_limit - Percona https://www.percona.com/blog/open_files_limit-mystery/
  4. MySQL :: MySQL 9.7 Reference Manual :: 6.3.2 mysqld_safe — MySQL Server Startup Script https://dev.mysql.com/doc/refman/9.7/en/mysqld-safe.html?utm_source=chatgpt.com
  5. mariadbd-safe | Server | MariaDB Documentation https://mariadb.com/docs/server/server-management/starting-and-stopping-mariadb/mariadbd-safe
  6. systemd (Linux) | Server | MariaDB Documentation https://mariadb.com/docs/server/server-management/starting-and-stopping-mariadb/systemd
  7. How to permanently raise ulimit 'open files' and MySQL 'open_files_limit' | DUNTUK https://duntuk.com/how-raise-ulimit-open-files-and-mysql-openfileslimit

留言