bri*_*tzy 2 python mysql mysql-python mysql-connector-python database-cursor
我有这个问题:我正在编写一些Python脚本,而到目前为止,我在整个脚本中使用单个MySQLConnector连接没有任何问题(仅在脚本末尾关闭它),最近我有一些问题。
如果我在脚本开头创建一个连接,类似于(我知道,忽略安全问题):
db_conn = mysql.connector.connect(user='root', password='myPassword', host='127.0.0.1', database='my_db', autocommit=True)
Run Code Online (Sandbox Code Playgroud)
然后总是像这样使用它:
db_conn.cursor(buffered=True).execute(...)
Run Code Online (Sandbox Code Playgroud)
或 fetch 等方法,我会收到如下错误:
Failed executing the SQL query: MySQL Connection not available.
Run Code Online (Sandbox Code Playgroud)
或者
Failed executing the SQL query: No result set to fetch from.
Run Code Online (Sandbox Code Playgroud)
或者
OperationalError: (2013, 'Lost connection to MySQL server during query')
Run Code Online (Sandbox Code Playgroud)
代码是正确的,我只是不明白为什么会发生这种情况。也许是因为我在异步中多次同时运行同一个函数(尝试了 2 次),所以也许对游标的并发访问会导致这种情况?
我发现有人每次都使用不同的数据库连接来修复它(此处)。
我尝试为数据库的每个查询创建一个新连接,现在根本没有错误。它工作得很好,但似乎有点矫枉过正。想象一下调用异步函数 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
Run Code Online (Sandbox Code Playgroud)
从那里开始情况会变得更糟,例如,当现有查询的结果集尚未关闭其结果集时,查询无法执行。或者更糟糕的是,您可以准备两个带有参数的查询,然后为错误的查询发送参数。
您可以对多个查询使用相同的数据库连接,但不要在并发执行的异步线程之间共享相同的连接。为了安全起见,每个异步例程都应该打开自己的连接。然后打开给定连接的线程可以使用该连接进行多个查询。
可以把它想象成一个呼叫中心,里面有几十个人,每个人都有自己的电话线。他们当然不应该尝试共享一条电话线并进行多次通话!唯一可行的方法是,电话中所说的每个字都带有一些识别信息,该信息属于哪个对话。“您好,我是史密斯先生,关于第 1234 号案件,您刚才问我的问题的答案是……”
但 MySQL 的协议并没有这样做。它假设每条消息都是前一条消息的延续,并且客户端和服务器都记住它是什么。