16

我正在使用 MySQLdb 模块从 python 处理 MySQL 5.0。

考虑一个简单的函数来加载和返回整个数据库表的内容:

def load_items(connection):
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM MyTable")
    return cursor.fetchall()

此查询旨在成为简单的数据加载,并且除了该单个SELECT语句之外没有任何事务行为。

运行此查询后,可能需要一段时间才能再次使用同一连接执行其他任务,但同时其他连接仍可在数据库上运行。

我是否应该在通话connection.commit()后立即cursor.execute(...)拨打电话以确保操作没有在连接上留下未完成的事务?

4

1 回答 1

20

您需要考虑以下两点:

  1. 有效的隔离级别
  2. 你想在交易中“看到”什么样的状态

MySQL 中的默认隔离级别REPEATABLE READ意味着,如果您SELECT在事务中运行两次,即使其他事务已提交更改,您也会看到完全相同的数据。

大多数时候,人们希望在运行第二个 select 语句时看到已提交的更改——这是READ COMMITTED隔离级别的行为。

如果您没有更改 MySQL 中的默认级别,并且您确实希望在同一事务中运行 SELECT 两次时看到数据库中的更改 - 那么您不能在“相同”事务中执行此操作,您需要提交您的第一个SELECT声明。

如果您真的在事务中看到一致的数据状态,那么您显然应该提交。

然后几分钟后,第一个进程执行一个事务性操作并尝试提交。这个提交会失败吗?

这完全取决于您对“事务性”的定义。您在关系数据库中所做的任何事情“都是事务性的”(实际上对于 MySQL 而言并非完全正确,但为了论证,如果您仅使用 InnoDB 作为存储引擎,您可以假设这一点)。

如果那个“第一个进程”只选择数据(即“只读事务”),那么提交当然会起作用。如果它试图修改另一个事务已经提交的数据并且你正在运行REPEATABLE READ你可能会得到一个错误(等到任何锁被释放之后)。在这种情况下,我对 MySQL 的行为不是 100%。

您真的应该使用您最喜欢的 SQL 客户端在两个不同的会话中手动尝试此操作,以了解行为。请务必更改您的隔离级别,以查看不同级别的效果。

于 2012-11-08T11:33:59.463 回答