关于使用事务从数据库读取数据似乎存在非常不同的观点。

引用自 DeveloperWorks 文章 交易策略:模型和策略概述:

如果您只读取数据,为什么需要交易?答案是你不。开始交易以执行仅读取操作会增加处理线程的开销,并可能导致数据库上的共享读取锁(取决于您使用的数据库类型以及设置的隔离级别)。

作为相反的意见,下面引用了 Hibernate 文档 非事务性数据访问和自动提交模式

我们的建议是不要在应用程序中使用自动企业模式,并且只有在具有明显的性能益处或将来的代码更改极不可能时才应用仅阅读交易。无论您是读取还是写数据,始终更喜欢定期的酸交易来对数据访问操作进行分组。

EclipseLink 邮件列表上也有类似的争论 这里.

那么真相在哪里呢?阅读交易是否是最佳实践?如果两者都是可行的解决方案,那么使用事务的标准是什么?

据我所知,只有隔离级别高于“已提交读”时才会产生影响。它是否正确?

有哪些经验和建议?

有帮助吗?

解决方案

Steven Devijver 提供了一些启动事务的充分理由,即使操作只是读取数据库:

  • 设置超时或锁定模式
  • 设置隔离级别

标准 SQL 要求,如果当前没有正在进行的事务,则即使是查询也必须启动新事务。有些 DBMS 不会发生这种情况 - 例如,那些具有自动提交模式的 DBMS(语句启动一个事务并在语句完成后立即提交它)。其他 DBMS 默认情况下使语句原子化(有效地自动提交),但使用诸如“BEGIN WORK”之类的语句启动显式事务,取消自动提交,直到下一次 COMMIT 或 ROLLBACK(IBM Informix Dynamic Server 就是这样一个 - 当数据库不是 MODE 时)美国标准协会)。

我不确定永远不要回滚的建议。它对只读事务没有影响,如果它让 DBA 烦恼,那么最好避免 ROLLBACK。但是,如果您的程序在没有执行 COMMIT 的情况下退出,则 DBMS 应该对您不完整的事务执行 ROLLBACK - 当然,如果它修改了数据库,并且(为了简单起见)即使您只选择了数据。

总体而言,如果要更改一系列操作的默认行为,请使用事务,即使该事务是只读的。如果您对默认行为感到满意,那么使用事务并不重要。如果您的代码要在 DBMS 之间移植,最好假设您需要事务。

其他提示

首先,这听起来像是一个过早的优化。正如Steven指出的那样,大多数理智的数据库无论如何都会让你进入一个事务,而他们真正做的就是在每个语句之后调用commit。因此,从这个角度来看,自动提交可能性能较差,因为每个语句都必须启动一个新事务。或者可能不是。只有基准测试会告诉我并且我敢打赌它不会对你的应用程序产生任何影响。

您希望始终使用交易的一个原因是保护的一致性。如果你开始摆弄只在你“需要”时手动宣布交易。然后你会在关键时刻忘记。或者那个假定的只读操作集突然不是,或者是因为后来的程序员没有意识到它应该是或者因为你的代码调用了一个隐藏写入的函数。例如,我将命令行数据库客户端配置为不自动提交。这意味着我可以用手指删除查询并仍然回滚。

正如所指出的那样,存在隔离级别。这允许您进行多次读取,而不必担心是否有其他进程已经写入您的数据之间,使您的读取有效地处于原子状态。这样可以省去一小时调试竞争条件。

最后,您通常可以将事务设置为只读。这会检查您的假设,如果有人试图写错误,则会出错。

这是一篇很好的文章,总结了一切。细节是特定于Oracle的,但概念是通用的。

如果要为默认超时以外的查询设置特定超时,或者如果要更改隔离级别,则只读事务需要事务。

此外,每个数据库 - 不了解异常 - 将在内部为每个查询启动一个事务。当不需要回滚时,通常认为没有回滚事务。

DBA可能正在监视回滚活动,在这种情况下,任何默认的回滚行为都会使它们烦恼。

因此,无论您是否启动交易,都会使用交易。如果您不需要它们,请不要启动它们,但不要在只读操作上进行回滚。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top