我应该回滚失败的 SELECT 语句还是提交成功的语句?

Posted

技术标签:

【中文标题】我应该回滚失败的 SELECT 语句还是提交成功的语句?【英文标题】:Should I rollback failed SELECT statements or commit successful ones? 【发布时间】:2011-01-23 17:33:39 【问题描述】:

出于习惯,我一直在我的应用程序代码中对所有 SQL 查询使用 try/catch 块,并在 catch 块的开头进行回滚。我也一直在提交那些成功的。 SELECTs 有必要这样做吗?它是否在数据库端释放了一些东西? select 语句没有改变任何数据,所以看起来有点毫无意义,但也许有一些我不知道的原因。

例如

try 
  $results = oci_execute($statement)
  oci_commit($connection);
  return $results;

catch 
  oci_rollback($connection)
  throw new SqlException("failed");

【问题讨论】:

【参考方案1】:

Oracle 中的SELECT 语句(除非它们是SELECT FOR UPDATE)从不锁定任何记录,也从不隐式打开事务。

除非您在事务中发出任何DML 操作,否则您提交还是回滚事务都无关紧要。

【讨论】:

@Quassnoi:嗯,可以。如果打开游标,则将为自打开游标以来正在进行的每个事务保留回滚(UNDO)。因此,如果要打开任何记录集,则确实需要在完成后关闭它们,以帮助可怜的 DBA 避免可怕的 ORA-01555。在某些数据库系统(我在看你,DB2)中,您确实需要在选择后提交以消除读锁。这可能就是编码标准演变而来的地方,或者只是单纯的偏执狂。 @Adam:UNDO 是由其他事务生成的,而不是保留光标的事务(我们假设它是只读的)。其他事务可能会更改数据,修改数据页(在这种情况下,UNDO 将被生成并保留到事务结束)和提交(在这种情况下,UNDO 被释放并标记为可以重写)。在只读游标中,只有当游标所需的数据被提交的并发事务覆盖时,才会生成ORA-01555。同样,游标本身不会锁定数据,不会生成任何UNDO,甚至不会锁定它需要的UNDO

以上是关于我应该回滚失败的 SELECT 语句还是提交成功的语句?的主要内容,如果未能解决你的问题,请参考以下文章

如果实现oracle中DDL语句的回滚

关于oracle的事务中,如何判断一条语句是不是成功执行

Spring @Transactional 浅谈

MySQL数据库—— 事务

在 Oracle 中提交和回滚 DML 语句

DDL 语句总是给你一个隐式提交,还是你能得到一个隐式回滚?