一、问题描述:
并没有像其他大佬一样,在Linux系统上安装MySql,而是采用windows+PHPstudy的方式简单部署mysql。
在写一个项目的时候需要连接数据库以完成验证用户信息的工作,出现报错如下(简略):
发生异常: OperationalError
(2003, "Can't connect to MySQL server on '49.232.218.203:3306' ([Errno 11001] getaddrinfo failed)")
socket.gaierror: [Errno 11001] getaddrinfo failed
During handling of the above exception, another exception occurred:
File "C:\Users\Administrator\Desktop\HealthManager\db.py", line 4, in <module>
connection = pymysql.connect(
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'IP地址手动打码括弧狗头括回' ([Errno 11001] getaddrinfo failed)")
Python 程序在尝试连接 MySQL 数据库时失败了,原因是无法解析主机地址。
二、解决过程:
似乎是很常见的问题,于是查看了防火墙规则是否开放3306、云平台规则是否开放3306,但都已开放。
保守起见,cmd查看一下。
netstat -an | findstr 3306
结果如下:
从 netstat
的输出来看,MySQL 服务已经在本地(127.0.0.1
)的 3306
端口监听,并且处于 LISTENING
和 ESTABLISHED
状态。当前 MySQL 可能只绑定在本地 127.0.0.1
,因此外部无法访问。需要将 MySQL 配置为绑定到所有 IP 地址,编辑 MySQL 的配置文件 my.cnf
(Linux 系统)或 my.ini
(Windows 系统)。但是打开my.ini的时候天塌了,里面没有 bind-address。
我是想通过设置bind-address=0.0.0.0来确保任何IP地址都可以连接数据库,但现在没有,后来查了资料发现,在MySql 8 中(版本在8.0及以上),bind-address参数已经被删除,默认绑定所有IP。由于我没有怎么仔细读,大致了解应该是这样的,保险起见,我还是尝试在后面手动添加bind-address=0.0.0.0,保存重启mysql后,在mysql命令行中输入语句查询bind-address状态
SHOW VARIABLES LIKE 'bind_address';
结果如下:
允许了所有IP地址连接,尝试连接,连接依旧失败。
想到可能是用户可能没有设置为可以从任何 IP 地址连接,于是使用在MYSQL命令行中使用语句开放权限并刷新权限。
GRANT ALL PRIVILEGES ON *.* TO '用户名'@'%' IDENTIFIED BY '密码';
FLUSH PRIVILEGES;
但此时报错:
mysql> GRANT ALL PRIVILEGES ON *.* TO 'lq'@'%' WITH GRANT OPTION;FLUSH PRIVILEGES;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 12
Current database: *** NONE ***
Query OK, 0 rows affected (1.21 sec)
Query OK, 0 rows affected (0.02 sec)
出现 ERROR 2006 (HY000): MySQL server has gone away
错误,通常意味着 MySQL 服务器与客户端之间的连接中断。那么这个问题是怎么导致的呢?
max_allowed_packet 过小:MySQL 的 max_allowed_packet
参数限制了单次请求的大小。如果这个值太小,可能会导致查询失败。可以尝试增加 max_allowed_packet
的值。 在 MySQL 配置文件 (my.cnf
或 my.ini
) 中,找到并修改 max_allowed_packet
这一行,我这里初始值是12M,一咬牙写了max_allowed_packet = 64M,当然也可以在命令行中输入
SET GLOBAL max_allowed_packet = 64 * 1024 * 1024;
问题依旧没有得到解决。
wait_timeout 参数过低:如果 MySQL 空闲时间过长,服务器可能会断开连接。增加 wait_timeout
的值可以避免连接超时。依旧是那个配置文件,找到wait_timeout,初始值120,我这里手动改成 28800 。 再寻找 interactive_timeout ,改成interactive_timeout = 28800 。
保存配置,重启mysql,重新执行设置权限语句,执行成功,测试连接,使用python代码创建几个简单的表,报错,连接不上。看了一眼地址,我采用的是IP : 端口的方式连接,于是去掉了端口,只留下IP地址:
import pymysql
# 创建 MySQL 数据库连接
connection = pymysql.connect(
host='40.233.234.123', # 并没有在IP后面加 :3306
user='用户名',
password='密码',
database='数据库名称',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
运行,没有报错,去MySql查询了一下数据库,均已创建成功。
三、不专业(存疑)的个人总结:
步骤:
1、检查用户名、密码、地址输入是否正确;
2、检查防火墙规则、云平台规则是否开放3306;
3、检查bind-address参数是否为0.0.0.0
4、检查用户权限是否设置为可以从任何 IP 地址连接
5、检查MySQL 配置问题:max_allowed_packet 过小、wait_timeout 参数过低、interactive_timeout参数与wait_timeout参数相同;
由于采用了很多方法,虽然最后通过修改wait_timeout 参数实现成功访问,但和前面做的步骤是否也有关,这一点尚未可知。至于这个方法是否适用于大家,我也不知道。
为什么要修改wait_timeout参数呢?我推断是因为该参数的默认值一般是网络速度千兆带宽,咱们自己的云端私服务端口带宽较小,只能调成等待连接时间更长,才行。
为什么连接时IP地址后面不指向端口3306?我推断服务器IP地址一般指向性没问题。默认MySQL(类)数据库端口:3306。
如果各位路过的大佬觉得哪里有什么问题,或者该总结并不是如我所推断那样而是另有原因,欢迎指正!因为我也对我自己的总结存疑,谢谢!