MySQL 连接器 (Python):每个查询的新数据库连接与单个连接
Posted
技术标签:
【中文标题】MySQL 连接器 (Python):每个查询的新数据库连接与单个连接【英文标题】:MySQLConnector (Python): New DB connection for each query vs. one single connection 【发布时间】:2021-03-18 01:06:02 【问题描述】:我有这个问题:我正在编写一些 Python 脚本,而到目前为止,我在整个脚本中使用单个 mysqlConnector 连接完全没有问题(仅在脚本末尾关闭它),最近我遇到了一些问题。
如果我在脚本开头创建一个连接,类似于(忽略安全问题,我知道):
db_conn = mysql.connector.connect(user='root', password='myPassword', host='127.0.0.1', database='my_db', autocommit=True)
然后总是像这样使用它:
db_conn.cursor(buffered=True).execute(...)
或者 fetch 等方法,我会得到如下错误:
Failed executing the SQL query: MySQL Connection not available.
或
Failed executing the SQL query: No result set to fetch from.
或
OperationalError: (2013, 'Lost connection to MySQL server during query')
代码是正确的,我只是不明白为什么会这样。也许是因为我在异步中多次同时运行同一个函数(尝试了 2 次),所以可能是对游标的并发访问导致了这个?
我发现有人通过每次使用不同的数据库连接来修复它 (here)。
我尝试为对数据库的每个查询创建一个新连接,现在完全没有错误。它工作正常,但似乎有点过头了。想象一下调用异步函数 10 次或 100 次......将会创建很多数据库连接。会不会造成问题?它会耗尽内存吗?而且,我猜它会慢下来。
有没有办法通过为所有查询保持相同的连接来解决这个问题?为什么会这样?
【问题讨论】:
【参考方案1】:MySQL 是一个有状态的协议(这种方式更像是 ftp 而不是 http)。这意味着如果您在同一个 MySQL 连接上运行多个发送和接收数据包的异步线程,则协议无法处理。服务器和客户端会混淆,因为消息会以错误的顺序到达。
我的意思是,如果不同的异步例程试图同时使用数据库连接,你很容易陷入困境:
async1: sends query "select * from table1"
async2: sends query "insert into table2 ..."
async1: expects to fetch rows of result set, but receives only rows-affected and last insertid
从那里开始变得更糟,例如,当现有查询的结果集尚未关闭其结果集时,查询无法执行。或者更糟糕的是,您可以准备两个带有参数的查询,然后为 错误 查询发送参数。
您可以对多个查询使用相同的数据库连接,但不要在并发执行的异步线程之间共享相同的连接。为了安全起见,每个异步例程都应该打开自己的连接。然后打开给定连接的线程可以将该连接用于多个查询。
可以将其想象为一个呼叫中心,其中数十人各有自己的电话线。他们当然不应该尝试共享一条电话线并进行多次对话!唯一可行的方法是,如果电话中说出的每个单词都带有一些识别信息,它属于哪个对话。 “您好,我是 Smith 先生来电咨询第 1234 号案件,您刚才问我的问题的答案是……”
但 MySQL 的协议并没有这样做。它假定每条消息都是前一条消息的延续,并且客户端和服务器都记得那是什么。
【讨论】:
以上是关于MySQL 连接器 (Python):每个查询的新数据库连接与单个连接的主要内容,如果未能解决你的问题,请参考以下文章
Mysql查询详解(条件查询、子查询、模糊查询、连接查询。。。)