Node.js 專案需讀寫遠端 Linux MySQL 時,常因權限、綁定地址、防火牆三大攔截而連線失敗。本文梳理 mysql2/mysql 驅動安裝、MySQL 用戶授權、bind-address 修改、Ubuntu iptables 開放 3306 及持久化規則的完整鏈路。
npm install mysql2 --save
# 或舊版驅動: npm install mysql --save
推薦 mysql2:支援 Promise/Prepared Statement、效能更好。
mysql -u root -p-- 方式 A: GRANT 授權 (5.7+ 推薦 CREATE USER 再 GRANT)
CREATE USER 'app_user'@'%' IDENTIFIED BY 'StrongPass123!';
GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'app_user'@'%';
FLUSH PRIVILEGES;
-- 方式 B: 直接修改 mysql.user 表 (不推薦,易遺漏 FLUSH)
-- UPDATE user SET host='%' WHERE user='app_user';
host='%' 允許任意 IP 連線;生產環境建議限定具體應用伺服器 IP (如 '10.0.1.%')。vim /etc/mysql/my.cnf # 或 /etc/my.cnf
# 找到 [mysqld] 區段
bind-address = 0.0.0.0
# 或註解掉 bind-address 行 (同效果)
重啟生效:systemctl restart mysql (或 service mysql restart)。
iptables -L -n -viptables -A INPUT -p tcp -i eth0 --dport 3306 -j ACCEPT
# 存規則
iptables-save > /etc/iptables.rules
# 編輯網卡啟動腳本
vim /etc/network/interfaces
# 在對應介面 (如 iface eth0 inet static) 下加入
pre-up iptables-restore < /etc/iptables.rules
驗證:應用伺服器執行 telnet db_ip 3306 或 nc -zv db_ip 3306,顯示 Connected/succeeded 即通。
const mysql = require('mysql2/promise');
const pool = mysql.createPool({
host: '192.168.1.100',
port: 3306,
user: 'app_user',
password: 'StrongPass123!',
database: 'mydb',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
// 使用
async function queryUsers() {
try {
const [rows] = await pool.execute('SELECT id, name FROM users WHERE status = ?', [1]);
console.log(rows);
} catch (err) {
console.error('DB Error:', err);
}
}
queryUsers();
| 現象 | 可能原因 | 排查指令 |
|---|---|---|
| ETIMEDOUT / ECONNREFUSED | 防火牆阻擋 / bind-address 錯誤 / 服務未啟動 | telnet ip 3306 / ss -ltnp | grep 3306 |
| ER_ACCESS_DENIED_ERROR | 用戶/密碼錯、host 不匹配、未 FLUSH PRIVILEGES | SELECT user,host FROM mysql.user; |
| ER_HOST_NOT_PRIVILEGED | 用戶 host 非 % 或具體 IP | UPDATE user SET host='%' WHERE user='...'; FLUSH PRIVILEGES; |
| ER_BAD_DB_ERROR | 資料庫名拼錯或未建立 | SHOW DATABASES; |
完成驅動安裝、授權、bind-address、防火牆四步驟,Node.js 即可穩定連線遠端 MySQL,建議生產環境再加上 SSL/TLS 加密連線 (ssl: {rejectUnauthorized: true}) 提升安全性。