PHP 执行 Oracle PL/SQL - OCI8 时何时会执行自动回滚?
我有执行存储过程 10 次的 PHP 代码。如果一个存储过程调用失败,它应该继续,并在最后提交事务。
它基本上看起来像这样:
$connection = getConn();
foreach($row as $i=>$j) {
$SQL = "BEGIN MYPROC.EXECUTE(:VAL1, :VAL2); END;";
$statement = OCIParse($connection, $SQL);
oci_bind_by_name($statement, 'VAL1', $row[i]['FIRSTVAL']);
oci_bind_by_name($statement, 'VAL2', $row[i]['SECONDVAL']);
$success = @OCIExecute($statement, OCI_DEFAULT);
if(!$success) {
print 'Exception in stored proc call';
}
else {
print 'Success';
}
}
oci_commit($connection);
我的问题是,如果在第五个存储过程调用中引发异常,是否会回滚到该点的所有存储过程调用?
I have PHP code that execute a stored procedure 10 times. If one stored procedure call fails, it should continue on, and at the end commit the transaction.
It basically looks like this:
$connection = getConn();
foreach($row as $i=>$j) {
$SQL = "BEGIN MYPROC.EXECUTE(:VAL1, :VAL2); END;";
$statement = OCIParse($connection, $SQL);
oci_bind_by_name($statement, 'VAL1', $row[i]['FIRSTVAL']);
oci_bind_by_name($statement, 'VAL2', $row[i]['SECONDVAL']);
$success = @OCIExecute($statement, OCI_DEFAULT);
if(!$success) {
print 'Exception in stored proc call';
}
else {
print 'Success';
}
}
oci_commit($connection);
My question is, if there is an exception raised in, say, the 5th stored proc call, will that roll back all the stored proc calls up to that point?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
只要每个过程都在同一个会话中执行,并且没有一个过程发出提交,那么它们所做的更改就可以回滚。您应该在循环外打开连接,然后在其中完成所有工作。就目前而言,您每次都通过循环进行连接,这是低效的并且不允许您执行您想做的事情。您还应该将 commit 语句放在循环之外。
也许是这样的:
As long as each procedure is executed in the same session, and none of them issue a commit, then the changes they make can be rolled back. You should open the connection outside the loop, then do all your work within that. As it stands now, you're connecting each time through the loop, which is inefficient and won't allow what you want to do. You should also take the commit statement outside the loop.
Something like this, perhaps:
我认为 PHP 驱动程序(而不是 Oracle)正在控制此处的提交。 这似乎表明从 PHP 5.3.2 (PECL OCI8 1.4),每次调用 OCIExecute(默认情况下)都会提交该语句,无论存储过程中有什么。
I think the PHP driver, and not Oracle, is controlling the commit here. This seems to indicate that as of PHP 5.3.2 (PECL OCI8 1.4), each invocation of the OCIExecute (by default) will commit the statement, regardless of what is in the stored procedure.
最近必须对此进行一些测试。当发生未处理的异常时,Oracle 似乎会部分回滚到同一会话的最顶层包含开始块或提交的点(并不总是一直返回到先前的提交)。给定一个带有 int id 和 varchar2 val 和 proc 的表:
然后执行以下操作:
一路回滚到“init”内的提交(也回滚了一个)。
与按顺序执行这些操作(从 Toad(自动提交关闭,每个块上按 F9,整个块按 f5)或 Sqlplus,中间有 /):
在 3 个内发生的异常然后回滚到“1”之后。然而,“ONE”仍然需要回滚或提交,因为它持有行锁(使用 TOAD 中的会话浏览器进行验证)。将此称为部分回滚,因为它不会一路返回到“init”调用中的提交并留下锁定的行。我假设这种情况更接近 PHP 和其他连接器可能正在做的事情。
Had to do some testing on this recently. When an unhandled exception occurs it seems Oracle does a partial rollback up to the point of the topmost containing begin block or commit for the same session (not always all the way back to the prior commit). Given a table with int id and varchar2 val and proc:
Then executing this:
rollsback all the way back to the commit within the 'init' (ONE rolled back as well).
Versus excecuting these in order (from either Toad (autocommit off, F9 on each block, f5 for whole thing) or Sqlplus with /'s in between):
The exception ocurring within THREE then rolls back to just after the 'ONE'. However the 'ONE' still needs to either be rolled back or committed since it is holding a row lock (verified with Session Browser in TOAD). Calling this a partial rollback because it doesn't go all the way back to the commit within the 'init' call and leaves a row locked. I am assuming this case is closer to what PHP might be doing and other connectors.