MySQL中的“Too many connections”的原因
问题分析
首先,我认为存在即为合理。这种提示并非说是MySQL的问题,而是我们程序的问题。
我举一个简单的例子,在很多爬虫项目中,我曾尝试使用PyMySQL来创建MySQL连接来进行相关的数据库操作。这样看着似乎没有什么问题,但当使用多线程以后,会发现原本创建的连接无法使用。这是因为:在PEP249中,相关线程安全的描述如下:
threadsafety | Meaning |
---|---|
0 | Threads may not share the module. |
1 | Threads may share the module, but not connections. |
2 | Threads may share the module and connections. |
3 | Threads may share the module, connections and cursors. |
我们可以得知,在标志为1时,线程之间可以共享模块,但无法共享连接。也就意味着我们的每一个线程连接数据库时,都需要创建相应的连接。
但这样就结束了么?
import pymysql.cursors
config = {
'host': '127.0.0.1',
'port': 3306,
'user': 'root',
'password': 'root',
'db': 'test',
'charset': 'utf8',
}
while True:
connection = pymysql.connect(**config)
# do something
connection.close()
貌似这么写是结束了,但是不久就会出现我们题目中所提到的问题->Too many connections.
这是为什么?
对,我也有怀疑,为什么我分明关闭了连接(connection.close()),为什么还会出现这种错误?
这个问题的答案就是,程序关闭了连接,而服务端并没有关闭。
怎么证明?
# 使用root登陆MySQL
show global variables like 'wait_timeout';
# 得到如下的信息
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout | 28800 |
+---------------+-------+
1 row in set (0.00 sec)
这便就是MySQL的默认的超时时间,即8个小时(单位是秒)。在查询结束后,将连接置于sleep状态,即使不存在网络等其他因素的问题,也不能允许客户端长久的建立连接,即超过8小时候,MySQL服务端主动关闭连接。
官方描述:
wait_timeout:The number of seconds the server waits for activity on a noninteractive connection before closing it. On thread startup, the session wait_timeout value is initialized from the global wait_timeout value or from the global interactive_timeoutvalue, depending on the type of client (as defined by the CLIENT_INTERACTIVE connect option to mysql_real_connect()).
科学合理的解决
我想,这就是使用ORM的一个原因了。