我使用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()
当我执行长时间查询时,代码引发超时错误,最后cursor
和connection
都被关闭(我调试conn._closed
以确认连接已关闭)。但是当我登录到mysql和show processlist
时,发现该进程仍然有效。
我的问题是,这正常吗?当我的代码中的查询超时时,如何杀死进程?我想出了一种在查询之前执行set session max_execution_time=60
的解决方法,但我认为这不是最佳实践。
这里是show processlist
的输出,我用sleep
表示长时间的查询,我认为结果是相同的,connection
在我的代码中已关闭,但是过程仍然存在。
答案 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)
read_timeout
用作基础timeout上的socket值。如果达到超时,套接字将引发OSError
(socket.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
时,脚本中将需要一个外部超时。