單機部署多個 MySQL 實例(不同 Port、不同資料目錄、不同配置),需要標準化的啟動腳本支援參數化端口、環境變數隔離、健康檢查與自動重試。
/usr/local/mysql/
├── my.cnf # 基礎配置模板
├── scripts/
│ ├── mysql_env.ini # 環境變數定義(用戶、密碼、Port 參數化)
│ └── start_mysql.sh # 啟動主腳本
└── bin/
└── mysqld_safe
mysql_env.ini# MySQL 初始化變數
MYSQL_USER=system # 管理用戶
MYSQL_PASS='password' # 管理密碼
# 參數檢查:支援傳入 Port,預設 3306
if [ $# -ne 1 ]; then
echo "mysql port is 3306"
MYSQL_PORT=3306
else
MYSQL_PORT=$1 # $1 為第一個位置參數
echo "mysql port is $1"
fi
start_mysql.sh#!/bin/sh
# 作者:ocpyang@126.com
MY_CNF=/usr/local/mysql/my.cnf
MYSQLD_SAFE=/usr/local/mysql/bin/mysqld_safe
# 載入環境變數
source /usr/local/mysql/scripts/mysql_env.ini
# 解析錯誤日誌路徑
ERRORLOG=`grep -i "^log-error" $MY_CNF | cut -d= -f2`
INIT_NUM=1
# 檢查 Port 佔用
PORTNUM=`netstat -lnt | grep ${MYSQL_PORT} | wc -l`
# 檢查啟動程式存在且可執行
if [ ! -x $MYSQLD_SAFE ]; then
echo "MySQL 啟動程式不存在或無執行權限:$MYSQLD_SAFE"
exit 1
fi
# Port 已被佔用
if [ $PORTNUM -eq 1 ]; then
echo "MySQL 進程已存在於 Port ${MYSQL_PORT},請先停止現有服務!"
exit 0
fi
# 啟動流程
echo "啟動本機 MySQL Port:${MYSQL_PORT}"
$MYSQLD_SAFE --defaults-file=$MY_CNF > /dev/null &
# 健康檢查重試邏輯(最多 5 次,間隔 5 秒)
while [ $INIT_NUM -le 5 ]; do
PORTNUM=`netstat -lnt | grep ${MYSQL_PORT} | wc -l`
echo "MySQL 啟動中... 請稍等..."
sleep 5
if [ $PORTNUM -eq 1 ]; then
echo "MySQL **** 啟動成功 ****"
exit 0
fi
INIT_NUM=$(($INIT_NUM + 1))
done
# 重試失敗
echo -e "MySQL 啟動失敗,請檢查錯誤日誌:`echo 'cat' ${ERRORLOG}`"
echo "*****************************************"
exit 0
echo "export PATH=/usr/local/mysql/scripts:\$PATH" >> ~/.bash_profile
source ~/.bash_profile
之後可直接在任意目錄執行:
start_mysql.sh 3307 # 啟動 Port 3307 實例
start_mysql.sh # 啟動預設 Port 3306 實例
| 特性 | 實現方式 | 價值 |
|---|---|---|
| 參數化 Port | $1 位置參數 + 預設值 | 單腳本支援多實例,無需複製修改 |
| 環境變數隔離 | source mysql_env.ini | 敏感資訊(密碼)與邏輯分離,便於權限控制 |
| 冪等性檢查 | netstat -lnt | grep Port | 防止重複啟動導致資料損壞 |
| 健康檢查重試 | while 迴圈 + sleep + 計數器 | 應對冷啟動慢、資源爭用等不確定因素 |
| 錯誤日誌定位 | grep log-error 解析 my.cnf | 失敗時精確指引排查路徑 |
# mysql_env.ini 新增
MY_CNF_BASE=/usr/local/mysql/conf
MY_CNF=${MY_CNF_BASE}/my_${MYSQL_PORT}.cnf
# /etc/systemd/system/mysql@.service
[Unit]
Description=MySQL Server on Port %i
After=network.target
[Service]
Type=forking
User=mysql
Group=mysql
ExecStart=/usr/local/mysql/scripts/start_mysql.sh %i
ExecStop=/usr/local/mysql/bin/mysqladmin -u system -p'password' -P %i shutdown
PIDFile=/var/run/mysql/mysql_%i.pid
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
使用:systemctl start mysql@3307、systemctl enable mysql@3307
# 啟動成功後註冊到 Consul/Etcd
curl -X PUT https://consul:8500/v1/agent/service/register \
-d '{"Name":"mysql","Port":'$MYSQL_PORT',"Check":{"TCP":"localhost:'$MYSQL_PORT'","Interval":"10s"}}'
| 現象 | 原因 | 解決 |
|---|---|---|
| Permission denied | 腳本無執行權限 / my.cnf 權限錯誤 | chmod +x start_mysql.sh、chown mysql:mysql my.cnf |
| Port 衝突 | 殘留進程 / 防火牆佔用 | lsof -i:3306 找到 PID kill、檢查防火牆規則 |
| 啟動超時 | InnoDB 恢復耗時 / 磁碟 IO 瓶頸 | 增加重試次數、調整 innodb_force_recovery、檢查磁碟健康 |
| 環境變數不生效 | source 路徑錯誤 / 變數名拼寫 | 腳本開頭加 set -x 除錯、檢查 echo $MYSQL_PORT |
本套腳本實現了 MySQL 多實例的標準化啟動、參數化配置、健康檢查與環境隔離。配合 systemd 與服務發現,可構建生產級的 MySQL 叢集管理體系。核心思想:**配置外部化、邏輯參數化、檢查自動化、失敗可觀測**。