我应该在单次选择后提交吗
Posted
技术标签:
【中文标题】我应该在单次选择后提交吗【英文标题】:Should I commit after a single select 【发布时间】:2012-10-28 13:45:28 【问题描述】:我正在使用 mysqldb 模块从 python 处理 MySQL 5.0。
考虑一个简单的函数来加载和返回整个数据库表的内容:
def load_items(connection):
cursor = connection.cursor()
cursor.execute("SELECT * FROM MyTable")
return cursor.fetchall()
此查询旨在进行简单的数据加载,除了单个 SELECT
语句之外没有任何事务行为。
运行此查询后,可能需要一段时间才能再次使用同一连接执行其他任务,但同时其他连接仍可在数据库上运行。
我是否应该在cursor.execute(...)
调用之后立即调用connection.commit()
以确保该操作没有在连接上留下未完成的事务?
【问题讨论】:
【参考方案1】:您需要考虑以下两点:
-
有效的隔离级别
您希望在交易中“看到”什么样的状态
MySQL 中的默认隔离级别是REPEATABLE READ
,这意味着如果您在一个事务中运行两次SELECT
,即使其他事务已提交更改,您也会看到完全相同的数据。
大多数时候,人们希望在运行第二个 select 语句时看到已提交的更改 - 这是 READ COMMITTED
隔离级别的行为。
如果您没有更改 MySQL 中的默认级别,并且您确实希望在同一事务中运行 SELECT 两次时看到数据库中的更改 - 那么您不能在“相同”事务,您需要提交您的第一个 SELECT
语句。
如果您确实想要查看事务中数据的一致状态,那么您显然应该不提交。
然后几分钟后,第一个进程执行一个事务性操作并尝试提交。这个提交会失败吗?
这完全取决于您对“事务性”的定义。您在关系数据库中所做的任何事情都是“事务性的”(实际上对于 MySQL 来说并不完全正确,但为了论证,如果您只使用 InnoDB 作为存储引擎,您可以假设这一点)。
如果“第一个进程”仅选择数据(即“只读事务”),那么提交当然会起作用。如果它试图修改另一个事务已经提交的数据并且您正在以REPEATABLE READ
运行,您可能会收到一个错误(在等待任何锁被释放之后)。在这种情况下,我对 MySQL 的行为不是 100%。
您真的应该使用您最喜欢的 SQL 客户端在两个不同的会话中手动尝试此操作,以了解行为。请务必更改您的隔离级别,以查看不同级别的效果。
【讨论】:
我想我的意思是,如果在使用相同的连接(或任何其他连接)调用load_items
后执行任何操作,我不希望调用 @987654327 @ 被视为同一事务的一部分。现在我已经阅读了您的答案并以这种方式提出了我的问题,很明显我正在寻找的行为是在SELECT
之后调用commit
。谢谢。
哦,您的最后建议是一个很好的建议,谢谢。这是我发布问题后一直在做的事情:D
甲骨文呢?以上是关于我应该在单次选择后提交吗的主要内容,如果未能解决你的问题,请参考以下文章