【问题标题】:I use pymysql to execute query in MySQL, but why the process is still alive after I close the connection?我使用pymysql在MySQL中执行查询,但是为什么关闭连接后进程仍然存在?
【发布时间】:2019-05-06 22:08:57
【问题描述】:

我使用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

【问题讨论】:

  • 显示来自show processlist的输出
  • 嗨@rdas我做了一个补充
  • 不要将文字作为图片发布

标签: python mysql pymysql


【解决方案1】:

PyMySQL 连接对象上的read_timeout 在读取操作期间用作底层socket 上的timeout 值。如果达到超时,套接字将引发OSError (socket.timeout) 的子类,该子类在连接的_read_bytes 方法中被捕获。
在处理该异常期间,将执行_force_close,最终将连接的self._sock 属性设置为None

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

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

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

您可能想看看 MySQL 的 kill 命令,它也在 PyMySQL connection 中实现,尽管没有记录。但是,当使用可能需要很长时间才能完成的语句执行 cursor.execute 时,这将需要在您的脚本中设置一个外部超时。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 2021-09-26
      • 2023-03-24
      • 1970-01-01
      相关资源
      最近更新 更多