“命令不同步;您现在不能运行此命令“在首次使用光标时

"commands out of sync; you can't run this command now" on first use of cursor

提问人:spraff 提问时间:11/15/2023 最后编辑:spraff 更新时间:11/15/2023 访问量:29

问:

我在 Django (Python) 中使用 MySQL。

这段代码的草稿版本可以工作并且很稳定,但它在不关闭游标的情况下创建了游标,我只是重写了它以通过进入/退出来管理游标。现在它不稳定。

class Cursor:

  def __init__ (self, db):
    self.db     = db
    self.cursor = db.DB_connection.cursor ()

  def __enter__ (self):
    return self

  def __exit__ (self, ex_type, ex_value, ex_traceback):
    if ex_value is not None:
      # log stuff
    self.cursor.close ()
    self.cursor = None

  def __del__ (self):
    if self.cursor is not None:
      # log stuff
      self.cursor.close ()

  def one (self, query, args):
    self.cursor.execute (query, args)
    return self.cursor.fetchone ()

class DB:

  def __init__ (self, my_stuff):
    self.DB_connection = connect (...)

  def get (self):
    return Cursor (self)

在应用程序中:

with DB_connection.get() as db:
  result = db.one ("SELECT ...", ...)

有时这和以前一样工作,但有时随机调用会失败db.one()

_mysql_connector.MySQLInterfaceError: Commands out of sync; you can't run this command now

此异常在 Cursor 的__exit__

谷歌搜索此错误告诉我,这意味着该光标上的早期 SELECT 仍然有未获取的结果。但这是无稽之谈,因为创建了一个新游标。with DB_connection.get() as db

此外,有时该过程只是存在而不打印任何异常信息。Docker 日志如下所示

www_1   | "GET /test_page HTTP/1.1" 200 16912
docker_www_1 exited with code 245

这些崩溃是不确定的,即使创建游标的视图中的代码是完全确定的。

我添加了一些 print 语句,这些语句显示,在应用程序流期间,只有 0 或 1 个游标同时存在。

在草稿版本中,而不是

with DB_connection.get() as db:
  result = db.one ("SELECT ...", ...)

它本来是这样的

db = DB_connection.get()
result = db.one ("SELECT ...", ...)

这非常稳定,尽管它泄漏了游标资源。我认为除了将光标包装在进入/退出中之外,由于它是稳定的,因此没有其他任何显着变化。

这是使用 API 的正确方法吗?

python mysql django database-cursor

评论

0赞 willeM_ Van Onsem 11/15/2023
__exit__如果存在异常,也会调用。在这种情况下,您有没有可能不关闭连接?目前还没有真正显示这是怎么回事。# log stuff
0赞 spraff 11/15/2023
它在通过它时打印,而不是在通过它之前打印。因此,此错误发生在块退出之前。Commands out of syncwith
0赞 willeM_ Van Onsem 11/15/2023
是的,但是之前有块吗?错误有时是发生在单个块上,还是有多个块?withwith
0赞 willeM_ Van Onsem 11/15/2023
另一个想法可能是在 之后关闭连接,所以 self.cursor.close();返回结果;one()self.cursor.execute(...); result = self.cursor.fetchone();
2赞 Bill Karwin 11/15/2023
游标只是一个 Python 类,MySQL 不知道也不关心您使用哪个游标,或者它是否是新游标。MySQL协议在连接级别处理状态。如果任何视图在数据库连接上留下了未获取的结果,则会导致此错误。从另一个视图或另一个光标调用它并不重要。

答: 暂无答案