MySQLdb 支持在单个连接上进行多个事务操作

8

在多个事务之间使用单个MySQLdb连接而不关闭连接是否可行?换句话说,类似于这样的内容:

conn = MySQLdb.connect(host="1.2.3.4", port=1234, user="root", passwd="x", db="test")

for i in range(10):
    try:
        cur = conn.cursor()
        query = "DELETE FROM SomeTable WHERE ID = %d" % i
        cur.execute(query)
        cur.close()
        conn.commit()

    except Exception:
        conn.rollback()

conn.close()

看起来工作正常,但我想再确认一下。


2
真遗憾你没有留下你的错误。在阅读修订版之前,我真的很困惑,因为我没有看到 Martijn Pieters 所说的误解是什么。 - Tétef
2个回答

22

我认为这里存在一种对事务构成的误解。

你的示例打开一个连接,然后在它上面执行一个事务。你在该事务中执行了多个SQL语句,但是在提交后完全关闭了它。当然,这很好。

执行多个事务(而不仅仅是SQL语句)看起来像这样:

conn = MySQLdb.connect(host="1.2.3.4", port=1234, user="root", passwd="x", db="test")

for j in range(10):
    try:
        for i in range(10):
            cur = conn.cursor()
            query = "DELETE FROM SomeTable WHERE ID = %d" % i
            cur.execute(query)
            cur.close()
        conn.commit()
    except Exception:
        conn.rollback()

conn.close()

上述代码提交了10个事务,每个事务包含10个单独的删除语句。

是的,你应该可以重复使用打开的连接而不会出现问题,只要不在多个线程之间共享该连接。

例如,SQLAlchemy 通过池化来重用连接,在应用程序需要时分配打开的连接。新的事务和语句将在应用程序的整个生命周期中在这些连接上执行,无需关闭,直到应用程序关闭为止。


是的,你说得对。我在简化示例以发布它时搞砸了。我会修复它的。 - d512
在我的情况下,共享连接线程会有什么问题? - d512
2
MySQLdb文档中可以看到:"如果您让两个线程同时使用一个连接,MySQL客户端库可能会抛出异常并崩溃。你已经被警告了。" - Martijn Pieters
太棒了。我现在明白了线程和连接应该如何相互交互。感谢您的提示。 - d512

0

先构建一个查询字符串,然后执行单个的MySQL语句会更好。例如:

query = "DELETE FROM table_name WHERE id IN ("
for i in range(10):
    query = query + "'" + str(i) + "', "
query = query[:-2] + ')'

cur = conn.cursor()
cur.execute(query)

那样更有效率,但我没有采用那种方式的原因。 - d512

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接