MySQLConnector (Python):每个查询的新数据库连接与一个连接

MySQLConnector (Python): New DB connection for each query vs. one single connection

我有这个问题:我正在写一些 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)。

我尝试为对数据库的每个查询创建一个新连接,现在完全没有错误。它工作正常,但似乎有点矫枉过正。想象一下调用 async 函数 10 次或 100 次……会创建大量的数据库连接。会不会出问题?会不会运行内存不足?而且,我想它会变慢。

有没有办法通过对所有查询保持相同的连接来解决这个问题?为什么会这样?

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

从那里变得更糟,例如,当现有查询的结果集尚未关闭其结果集时,无法执行查询。或者更糟糕的是,您可以准备两个具有参数的查询,然后随后为 错误的 查询发送参数。

您可以对多个查询使用相同的数据库连接,但不要在并发执行的异步线程之间共享相同的连接。为了安全起见,每个异步例程都应该打开自己的连接。然后打开给定连接的线程可以使用该连接进行多个查询。

可以把它想象成一个呼叫中心,那里有几十个人,每个人都有自己的 phone 线路。他们当然不应该尝试共享一条 phone 线路并进行多次对话!唯一可行的方法是,如果在 phone 上说出的每个词都带有它所属对话的一些识别信息。 “嗨,我是 Smith 先生,就第 1234 号病例来电,您刚才问我的问题的答案是……”

但是MySQL的协议并没有这样做。它假定每条消息都是前一条消息的延续,并且客户端和服务器都记得那是什么。