| 根因類別 | 典型場景 | 核心機制 |
| Socket 檔案遺失 | /tmp 清理、手動刪除、Plesk 等面板誤操作 | Unix Domain Socket 是客戶端與本地 `mysqld` 通訊的端點,`mysqld` 啟動時建立,關閉時刪除 |
| mysqld 進程未運行 | 崩潰、OOM Killer、手動 kill、啟動腳本失敗 | 無進程自然無 socket,客戶端連線失敗 |
| Socket 路徑不匹配 | my.cnf client/server 區塊 socket 參數不一致、多實例 | 客戶端讀取 `[client] socket=`,伺服端讀取 `[mysqld] socket=`,雙方必須一致 |
分級排查與修復流程
Level 1:確認 mysqld 進程狀態
ps aux | grep mysqld
# 正常應見兩進程:
# mysql ... /usr/local/libexec/mysqld --basedir=... --datadir=...
# root ... /bin/sh /usr/local/bin/mysqld_safe --user=mysql --datadir=...
- ✅ **有進程** → 進 Level 2
- ❌ **無進程** → 進 Level 3 (啟動服務)
Level 2:Socket 路徑對齊檢查
# 1. 找出實際 socket 位置
find / -name mysql.sock 2>/dev/null
# 或
netstat -ln | grep mysql
# 或檢查錯誤日誌
grep -i socket /var/log/mysql/error.log
# 2. 檢查配置一致性
grep socket /etc/my.cnf /usr/local/etc/my.cnf ~/.my.cnf
# [mysqld] socket=/tmp/mysql.sock
# [client] socket=/tmp/mysql.sock ← 必須一致
# 3. 客戶端強制指定 socket
mysql -u root -p --socket=/actual/path/mysql.sock
# 或 TCP 繞過 socket
mysql -u root -p -h 127.0.0.1 --port=3306
Level 3:服務重啟失效深度排查
# 1. 嘗試標準重啟
/etc/rc.d/mysql restart
# 或
service mysql restart
# 2. 若報相同 ERROR 2002 → 進程卡住/鎖檔案殘留
ps aux | grep mysql
kill -TERM
kill -TERM
# 強制殺掉
kill -9
# 3. 檢查鎖檔案
ls -la /var/run/mysqld/ /tmp/ /var/lib/mysql/ | grep -E '\.pid|\.sock|\.lock'
rm -f /var/run/mysqld/mysqld.pid /tmp/mysql.sock
# 4. 乾淨啟動
/etc/rc.d/mysql start
# 或
mysqld_safe --user=mysql --datadir=/var/db/mysql &
實戰案例:Plesk 導致 socket 遺失的完整修復記錄
- 發現:`mysql -u root -p` 報 ERROR 2002
- 搜尋:`find / -name mysql.sock` → 無結果
- 推斷:Plesk 安裝腳本清理 `/tmp` 誤刪 socket,但 `mysqld` 進程仍存活
- 嘗試重啟:`mysql restart` → 同樣 ERROR (因客戶端仍嘗試連舊 socket)
- 檢查進程:`ps aux | grep mysql` → 發現兩進程正常運行
- 殺掉進程:`kill `
- 重啟服務:`/etc/rc.d/mysql start` → 依然失敗
- 重裝嘗試:`cd /usr/ports/databases/mysql41-server && make deinstall && make reinstall` (險!)
- 靈機一動:`reboot` 重開機
- 驗證:開機後 `mysql -u root -p` → **成功連線!**
為什麼 Reboot 有效?
- 系統啟動腳本 `/etc/rc.d/mysql` 啟動 `mysqld_safe` → `mysqld` **重新建立 socket**
- 舊進程被徹底清理,無殘留鎖/共享記憶體
- `mysqld` 啟動邏輯:**每次啟動自動建立 socket 檔案** (放於 `my.cnf` 指定路徑)
預防再發生:配置與監控鐵律
- ✅ **統一 Socket 路徑**:`[mysqld]` 和 `[client]` 區塊**完全相同**的 `socket=/var/run/mysqld/mysqld.sock` (避免 `/tmp` 定期清理)
- ✅ **pid-file 目錄獨立**:`pid-file=/var/run/mysqld/mysqld.pid`,目錄屬主 `mysql:mysql`,權限 `755`
- ✅ **啟動腳本健壯化**:啟動前檢查並清理殘留 `.pid` `.sock`,`mysqld_safe` 監控自動重啟
- ✅ **監控告警**:
- 進程存活:`systemd` / `monit` / `supervisord` 監控 `mysqld`
- Socket 存在性:`test -S /var/run/mysqld/mysqld.sock`
- 連線測試:`mysqladmin -u monitor -p ping` 定期探活
- ✅ **禁止手動操作 `/tmp` 下 mysql 相關檔案**
快速參考卡片
| 情境 | 最快指令 | 說明 |
| 懷疑 socket 路徑錯 | `mysql -u root -p -h 127.0.0.1` | 強制 TCP 連線繞過 socket |
| 確認進程卡住 | `pkill -9 mysqld; pkill -9 mysqld_safe` | 暴力清理再啟動 |
| 生產環境不敢 kill | `mysqladmin -u root -p shutdown` | 優雅關閉,再啟動 |
| 多實例環境 | `mysql --defaults-file=/etc/my.cnf.3307 -u root -p` | 指定專屬配置檔 |
| Docker 容器 | `docker exec -it mysql mysql -u root -p` | 容器內直連 |
結語
ERROR 2002 看似嚇人,本質是「客戶端找不到伺服端的 Unix Socket 端點」。掌握「進程存活 → Socket 存在 → 路徑一致」三步排查鏈,配合「Socket 移出 `/tmp`、啟動腳本自清理、監控全覆蓋」三大預防措施,即可徹底根治。記住:**Reboot 是最終武器,但標準化運維才是長久之計**。
- 上一篇文章: MySQL 與 OpenOffice Base 完美整合:兩種部署方案從零構建視覺化資料庫開發環境
- 下一篇文章: 基於 MySQL + ProFTPD 的個人資料異地備份系統:架構設計與實作細節
Copyright ©
程式碼之家 All Rights Reserved