在PDO中,事务应该在哪里回滚?

6
我的问题是,我有一个数据库设计,来自这个链接is my database overdesigned? 编辑* 好的,也许使用事务?但如果失败了,我应该在哪里放置回滚?
 $dbConnect->beginTransaction();
 $RegisterInsert = $dbConnect->prepare("INSERT INTO companies (
    `name`, `address`, `email`, `phone`, `link`, `verified`) VALUES (
    :name, :address, :email, :phone, :link, :verified)");
    $RegisterInsert->execute($RegisterData);

    $RegisterData2['CID'] = $dbConnect->lastInsertId();  

    $RegisterInsert = $dbConnect->prepare("INSERT INTO users_companies (
    `UID`, `CID`, `role`) VALUES (
    :UID, :CID, :role)");
    $RegisterInsert->execute($RegisterData2);
    $dbConnect->commit();

我应该把回滚放在哪里?

谢谢


是的,我知道,我不知道这个问题的最佳标题,请编辑它。 - user396420
2
您应该始终使用事务和适当的错误处理来确保您的数据库保持一致(如果第二个插入由于磁盘空间不足或MySQL崩溃而失败会发生什么),但并非所有MySQL表类型都支持使用事务...例如,MyISAM不支持,InnoDB支持。 - Mark Baker
在第一个 $RegisterInsert->execute 后加入错误捕获,并在出现错误时回滚,否则执行 $dbConnect->lastInsertId(); 和第二个 $RegisterInsert->execute,在第二个操作后再次加入错误捕获并回滚,否则提交。 - Mark Baker
好的,你能给我一个例子吗?请看这里:https://dev59.com/H0XRa4cB1Zd3GeqPveWr 它说如果提交失败,commit会回滚,那么我们不需要添加回滚或错误处理,这是真的吗?谢谢。 - user396420
1
将autoCommit设置为false应该会在事务结束时强制执行回滚,除非您明确提交。我不知道如果提交失败是否会自动回滚。我更喜欢在代码中使所有提交和回滚明确化,这样当另一个开发人员查看它时就不会有误解。 - Mark Baker
显示剩余5条评论
2个回答

5

一次事务应该以rollback()commit()其中之一结束(仅限其中一个)。

通常与if...else语句一起使用,因为逻辑上只应执行其中一个。

$dbConnect->beginTransaction();

//somecode
//$dbConnect->execute( $someInsert );
//some more code
//$result = $dbConnect->execute( $someSelect );
//$nextRow = $result->fetchRow();

//either commit or rollback!
if( $someResultCheck == true )
    $dbConnect->commit();
else
    $dbConnect->rollback();

当查询涉及到复杂逻辑时,通常会使用事务。

如果您正在使用MySQL,请确保不要在表中使用MyISAM引擎,因为它不支持事务。


除非将autoCommit设置为false,否则您的代码无法自动回滚。 - Mark Baker
好的,我们应该在RegisterInsert中进行$someResultCheck吗?我说得对吗? - user396420
@kaskus:没错。你只有在两个插入语句都成功执行时才想提交。所以你需要执行 $someResultCheck = $RegisterInsert->execute($stmt); - Kalyan02
@mark:autoCommit 只对事务外的语句有影响,在事务内部手动开始事务时不适用。 - Kalyan02
@Kalyan - 感谢你的澄清。正如我在其他地方所说,我总是编写显式事务启动和提交/回滚的代码,因为这样其他开发人员阅读代码时就不会有任何误解了。 - Mark Baker

5

一旦您知道整个事务将失败,您应该回滚到目前为止所做的工作,并且不再尝试任何进一步的更新 - 因此伪代码如下:

 function do_updates(array updates)
 { 
    PDO->beginTransaction();
    foreach (updates as statement) {
       run statement
       if failed {
         PDO->rollback(); 
         return false;
       }
    }
    return PDO->commit();

HTH

C.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接