只读DB访问的事务?

关于使用事务从数据库中读取似乎有很不同的意见。

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

如果你只是读数据,为什么你需要一个交易? 答案是你没有。 启动事务以执行只读操作会增加处理线程的开销,并可能导致数据库上的共享读取locking(取决于您使用的数据库types以及隔离级别设置为什么)。

相反的观点是从Hibernate文档非事务性数据访问和自动提交模式引用如下

我们的build议是,不要在应用程序中使用自动提交模式,只有在有明显的性能好处或未来的代码更改不太可能时,才应用只读事务。 无论您是读取还是写入数据,始终都希望定期使用ACID事务来对您的数据访问操作进行分组。

EclipseLink邮件列表在这里也有类似的争论。

那么真相在哪里呢? 是否阅读最佳做法的交易? 如果两者都是可行的解决scheme,使用交易的标准是什么?

据我所见,只有当隔离级别高于“读取提交”时才会有所作为。 它是否正确?

有什么经验和build议?

即使操作只是读取数据库,Steven Devijver提供了一些开始事务的好理由:

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

标准SQL要求,如果没有正在进行的事务,即使查询也必须启动新的事务。 有数据库pipe理系统哪里不会发生什么 – 例如那些与自动提交模式,(语句启动一个事务,并立即提交声明完成)。 其他DBMS在默认情况下使语句primefaces化(有效自动提交),但使用诸如“BEGIN WORK”之类的语句启动显式事务,取消自动提交,直到下一个COMMIT或ROLLBACK(IBM Informix Dynamic Server就是这样 – 当数据库不是MODE ANSI)。

我不确定不会回滚的build议。 这对只读事务没有任何影响,并且在很大程度上会让DBA恼火,所以最好避免ROLLBACK。 但是如果你的程序没有执行COMMIT就退出了,那么DBMS应该对你的不完整事务做一个ROLLBACK–当然如果​​它修改了数据库,并且(为了简单起见)即使你只select了数据。

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

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

另外,每个数据库(不知道exception情况)都将在内部为每个查询启动一个事务。 当不需要回滚时,通常认为没有做回滚事务。

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

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

首先,这听起来像是一个不成熟的优化。 正如Steven所指出的那样,大多数正常的数据库都会把你放到一个事务中,而他们真正所做的就是在每个语句之后调用commit。 所以从这个angular度来看,自动提交可能是性能较差,因为每个语句都必须启动一个新的事务。 或者可能不是。 只有基准testing会告诉我,我敢打赌,它不会让你的应用程序有一个重大的变化。

为什么要总是使用交易的一个原因是保护的一致性。 如果你只是在“需要”的时候开始手动地声明一个事务,那么你将在关键时刻忘记。 或者那个被认为是只读的操作集合突然不是,或者是因为后来的程序员没有意识到它应该是这样,或者是因为你的代码调用了一个隐藏的函数。 例如,我将我的命令行数据库客户端configuration为不自动提交。 这意味着我可以胖手指删除查询,仍然回滚。

正如指出的那样,存在隔离级别。 这使您可以进行多次读取,而无需担心其他进程是否将数据写入到这些进程之间,从而使您的读取有效地进行primefaces化。 这将节省你从一个小时的debugging竞争条件。

最后,您可以经常将事务设置为只读。 这将检查您的假设,并会错误,如果有东西试图写。

这里总结了一篇不错的文章。 细节是Oracle特有的,但概念是通用的。