我使用pymysql在MySQL中执行查询,但是在关闭连接后为什么该过程仍然存在?

时间:2019-05-06 09:22:07

标签: python mysql pymysql

我使用pymysql连接mysql,并在连接时设置了read_timeout

conn = pymysql.connect(host=host,port=port,user=user,passwd=passwd,read_timeout=60)

我的查询代码在这里:

try:
    cur.execute(sql)
    rows = cur.fetchall()
except:
    # timeout
    logging.error()
finally:
    cur.close()
    conn.close()

当我执行长时间查询时,代码引发超时错误,最后cursorconnection都被关闭(我调试conn._closed以确认连接已关闭)。但是当我登录到mysql和show processlist时,发现该进程仍然有效。

我的问题是,这正常吗?当我的代码中的查询超时时,如何杀死进程?我想出了一种在查询之前执行set session max_execution_time=60的解决方法,但我认为这不是最佳实践。

这里是show processlist的输出,我用sleep表示长时间的查询,我认为结果是相同的,connection在我的代码中已关闭,但是过程仍然存在。

show processlist output

2 个答案:

答案 0 :(得分:0)

您需要在关闭连接之前提交事务。由于事务尚未提交到数据库,因此该过程必须处于活动状态。 在初始化conn.autocommit=true的开始或初始化期间添加conn

conn = pymysql.connect(host=host,port=port,user=user,passwd=passwd,read_timeout=60, autocommit=True)

或者,您可以在关闭连接之前使用conn.commit()

答案 1 :(得分:0)

在读取操作期间,PyMySQL连接对象上的

read_timeout用作基础timeout上的socket值。如果达到超时,套接字将引发OSErrorsocket.timeout)的子类,该子类将被连接的_read_bytes方法捕获。
在处理该异常期间,{ {3}}被执行,最终将连接的self._sock属性设置为None

当代码到达finally块时,在执行conn.close()期间剩下要做的就是将_closed设置为True。
如果此时_sock不是None,则close方法还将尝试通过套接字向服务器发送_force_close,但是由于客户端套接字已经存在关闭,不会发生。

从服务器的角度来看,客户端无言地断开了连接。不幸的是,很难找到有意义的文档来说明在这种情况下到底发生了什么。

通常,在连接超时时,应回滚待处理的事务。但是,我不确定客户端关闭其套接字是否会导致服务器端立即超时,如COM_QUIT中所建议。
同样,使用MySQL的sleep函数进行测试可能不是一个好主意。它可能会完全挂起处理您的连接和查询的线程,使其无法及时检测到丢失的连接。

您可能想看看MySQL的this Q&A命令,该命令也已在PyMySQL kill中实现,尽管未记录。但是,在对可能花费太长时间才能完成的语句进行cursor.execute时,脚本中将需要一个外部超时。