在MySQL中,如果訪問/連接MySQL資料庫時遇到“ERROR 2003 (HY000): Can't connect to MySQL server on 'xxx.xxx.xxx.xxx:xxx' (111)”這個錯誤,我們應該從哪些方面進行考慮和排查問題呢? 下圖是我總結整理的一個思維導圖, ...
在MySQL中,如果訪問/連接MySQL資料庫時遇到“ERROR 2003 (HY000): Can't connect to MySQL server on 'xxx.xxx.xxx.xxx:xxx' (111)”這個錯誤,我們應該從哪些方面進行考慮和排查問題呢? 下圖是我總結整理的一個思維導圖,在遇到這個錯誤時的排查方向和排查思路。
下麵來演示/介紹一個比較特殊的案例,在伺服器上訪問當前主機的MySQL時遇到了“ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1:7306' (111)”
$ mysql -h 127.0.0.1 -u test -p --port=7306
Enter password:
ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1:7306' (111)
$ perror 111
OS error code 111: Connection refused
其實訪問本地MySQL,根本不用檢查127.0.0.1這個IP是否能ping通,不過為了以防萬一,我們還是驗證一下
$ ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.046 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.073 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.071 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.072 ms
64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.071 ms
^C
--- 127.0.0.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4099ms
rtt min/avg/max/mdev = 0.046/0.066/0.073/0.013 ms
檢查MySQL實例狀態
然後我們檢查一下MySQL服務是否正常,MySQL實例是否Crash掉了。
方式1:
$ sudo systemctl status mysqld.service
● mysqld.service - MySQL Server
Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
Active: active (running) since Mon 2023-03-13 15:01:43 CST; 1 weeks 2 days ago
Docs: man:mysqld(8)
http://dev.mysql.com/doc/refman/en/using-systemd.html
Main PID: 143115 (mysqld)
Status: "Server is operational"
Tasks: 47 (limit: 49256)
Memory: 1.4G
CGroup: /system.slice/mysqld.service
└─143115 /opt/mysql/mysql8.0/bin/mysqld --defaults-file=/data/conf/my.cnf
Mar 13 15:01:40 yictmysqlu01 systemd[1]: Starting MySQL Server...
Mar 13 15:01:43 yictmysqlu01 systemd[1]: Started MySQL Server.
方式2:
ps -Af | grep mysqld | grep -v grep
mysql 143115 1 1 Mar13 ? 03:47:43 /opt/mysql/mysql8.0/bin/mysqld --defaults-file=/data/conf/my.cnf
如上所示,MySQL實例正常的,所以可以排除MySQL實例關閉或MySQL實例Crash的情況。
檢查MySQL的監聽埠
使用下麵命令檢查MySQL的監聽埠
$ netstat -lnp | grep mysql
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 192.168.9.203:7306 0.0.0.0:* LISTEN 143115/mysqld
tcp6 0 0 :::33060 :::* LISTEN 143115/mysqld
unix 2 [ ACC ] STREAM LISTENING 3188552 143115/mysqld /tmp/mysqlx.sock
unix 2 [ ACC ] STREAM LISTENING 3191315 143115/mysqld /tmp/mysql.sock
如上所示,監聽埠為7306,訪問MySQL時指定的埠號也是7306,沒有什麼毛病。因此也可以排查這個因素。
檢查參數bind-address
檢查MySQL的配置文件中的bind-address參數
方式1:
$ grep bind_address my.cnf
bind_address=192.168.9.203
方式2:
mysql> SELECT VARIABLE_NAME, VARIABLE_VALUE
-> FROM performance_schema.global_variables
-> WHERE VARIABLE_NAME = 'bind_address';
+---------------+----------------+
| VARIABLE_NAME | VARIABLE_VALUE |
+---------------+----------------+
| bind_address | 192.168.9.203 |
+---------------+----------------+
1 row in set (0.01 sec)
mysql>
bind-address的設置有以下三種情況:
bind-address=127.0.0.1 #只允許本機訪問。
bind-address=某個網卡的ip #例如bind-address=192.168.9.203,只能通過ip為192.168.9.203的網卡訪問。
bind-address=0.0.0.0 #此規則是系統預設配置,監聽所有網卡,即允許所有ip訪問。
這裡由於設定參數bind_address=192.168.9.203,所以當我們使用127.0.0.1訪問資料庫就會被拒絕,從而拋出上面的錯誤。
那麼這裡有一個問題,如果資料庫裡面創建了兩個賬號test@'127.0.0.1'和test@'localhost',那麼test@'localhost'是否也會遇到這個錯誤呢?你的答案是會還是不會呢? 正確答案是不會,因為localhost和127.0.0.1兩者是有所區別的(下麵部分內容來自參考資料[1]):
一、原理不同:
localhost的原理是不經網卡傳輸,不會受到網卡協議的限制。設置程式時本地服務用localhost,localhost不會解析成IP,也不會占用網卡、網路資源。 127.0.0.1的原理是經過網卡傳輸的,依賴網卡協議,並受到網卡相關協議的限制。使用IP訪問的時候,等於本機是通過網路再去訪問本機,會涉及到網路用戶的許可權。
二、概念不同
localhost:也可以叫是local,正確的解釋是:本地伺服器的意思。它可以被配置為任意的IP地址可以通過hosts這個文件進行更改,不過通常情況下都指向:127.0.0.1 127.0.0.1:在windows系統的正確解釋是:本機地址的意思。127.0.0.1是保留地址之一,用來檢驗本機TCP/IP協議棧,可以Ping回送地址。如果回送地址Ping不通,就說明IP堆棧出了故障。如果通的話,表明網路出了問題。
三、指向不同
localhost是一個保留功能變數名稱(RFC 2606) ,為了避免同狹義定義主機名混淆而單獨列出。它不僅指向 127.0.0.1 這個IP地址,它同時還可以指向ipv6 的地址 。 127.0.0.1 是回送地址,指本地機,測試使用。回送地址(127.x.x.x)是本機回送地址(Loopback Address),即主機IP堆棧內部的IP地址,主要用於網路軟體測試以及本地機進程間通信,無論什麼程式,一旦使用回送地址發送數據,協議軟體立即返回,不進行任何網路傳輸。
具體原因如下:
mysql -h 127.0.0.1 訪問MySQL的時候,使用 TCP/IP 連接
mysql -h localhost 訪問MySQL的時候,它不會使用 TCP/IP 連接的,而使用Unix socket;此時,MySQL Server則認為該 client 是來自 “localhost”
參考資料
參考資料: https://www.termilk.com/181.html