gpt4 book ai didi

PHP、MySQL、PDO 事务 - 调用 commit() 后是否可以使用 rollBack()?

转载 作者:行者123 更新时间:2023-11-29 04:17:39 25 4
gpt4 key购买 nike

我查看了 rollBack() 的资源, commit()various transaction stuff , 但我找不到在调用 commit() 之后是否可以调用 rollBack()

情况是这样的:

我有两个不同的数据库:$dbu = new PDO(..db1..)$dbb = new PDO(..db2..)

两个数据库都有在单个函数中更新的表。操作是 all or none - 要么所有表都成功更新,要么一个都不更新。

使用两个单独的事务,如果 $dbu 的事务成功完成,但是 $dbb 的事务失败,我必须撤消第一个所做的事情交易:

代码块 1

$dbu->beginTransaction();
try{
$stmt = $dbu->prepare(...);
$stmt->execute();

// stuff

$dbu->commit();
}catch(Exception $e){
// do stuff

$dbu->rollBack();
exit();
}

$dbb->beginTransaction();
try{
$stmt = $dbb->prepare(...);
$stmt->execute();

// stuff

$dbb->commit();
}catch(Exception $e){
// do stuff

$dbb->rollBack();

// Need to undo what we did
$dbu->beginTransaction();
try{
$stmt = $dbu->prepare(...);
$stmt->execute();

// opposite of whatever operation was in the first transaction

$dbu->commit();
}catch(Exception $e){
}

exit();
}

如果两个主要事务之间的连接出现问题,这会很困惑且不可靠。

所以我想做的是将第二个事务嵌套在第一个事务中。我能够这样做似乎是合乎逻辑的,因为 $dbu$dbb 是两个独特的 PDO 对象,它们指向两个独立的数据库。看起来像:

代码块 2

$dbu->beginTransaction();
try{
$stmt = $dbu->prepare(...);
$stmt->execute();

// stuff

$dbb->beginTransaction();
try{
$stmt = $dbb->prepare(...);
$stmt->execute();

// stuff

$dbb->commit();
}catch(Exception $e){
// do stuff

$dbb->rollBack();
$dbu->rollBack(); // Since $dbu was first part of transaction, it needs to be rolled back too
exit();
}

$dbu->commit();
}catch(Exception $e){
// do stuff

$dbu->rollBack();
$dbb->rollBack(); // **THIS IS THE TRICKY LINE!**
exit();
}

由于 $dbucommit() 在整个 $dbb 事务之后被调用,这种情况可能在 $dbb 成功而 $dbu 失败的地方出现。如果发生这种情况,我需要撤消在 $dbb 事务中所做的操作。

所以...

我可以调用 $dbb->rollBack();(接近代码块 2 的末尾)AFTER $dbb ->commit(); 运行了吗?或者我是否陷入了与最初相同的情况,我必须手动撤销 $dbb 交易中发生的任何事情?同样,这并不理想。如果连接在此过程中断开,我可能会在 $dbb 表中留下不应该存在的数据(因为 $dbu 事务失败)。

也许我可以将这两个事务合并到一个 try/catch block 中?

代码块 3

$dbu->beginTransaction();
$dbb->beginTransaction();

try{
$stmt = $dbu->prepare(...);
$stmt->execute();

$stmt2 = $dbb->prepare(...);
$stmt2->execute();

// stuff

$dbu->commit();
$dbb->commit();
}catch(Exception $e){
// do stuff

$dbu->rollBack();
$dbb->rollBack(); // **THIS IS THE TRICKY LINE!**
exit();
}

但这看起来与代码块 2 没有太大区别,因为我们仍然可以遇到 $dbu->commit(); 成功的情况,但是 $dbb->commit(); 失败了。如果发生这种情况,那么我们仍在尝试调用 $dbu->rollBack(); 在其伙伴提交已被处理后。

如果我不能commit() 之后调用rollBack(),是否有解决这个2-DB 问题的常用方法?与 rollBack() 一样高效并且不需要整个额外事务来撤消前一个操作的东西。

编辑 1

添加到代码块 3,我可以在调用时验证每个执行吗?

代码块 4

$dbu->beginTransaction();
$dbb->beginTransaction();

try{
$stmt = $dbu->prepare(...);
if(!$stmt->execute()){
throw new Exeption('something somethign');
}

$stmt2 = $dbb->prepare(...);
if(!$stmt2->execute()){
throw new Exeption('something two');
}

// stuff

$dbu->commit();
$dbb->commit();
}catch(PDOException $e){
// do stuff

$dbu->rollBack();
$dbb->rollBack(); // **THIS IS THE TRICKY LINE!**
exit();
}catch(Exception $e){
// do stuff

$dbu->rollBack();
$dbb->rollBack(); // **THIS IS THE TRICKY LINE!**
exit();
}

这是否有助于确保两个 commit 语句有最大可能的成功机会?还是 try/catch block 会在调用自定义 block 之前自动抛出 PDOException?最好有一个简单的标识符来知道哪个事务失败,而不是整个 $e->getMessage();

最佳答案

不可能在不同的数据库连接之间进行正确的事务处理。

虽然您可以采取一些尴尬的变通办法,但它不会让您的交易成为真实的交易。

因此,您要么将所有操作都保存在一个数据库中,要么忘记事务

关于PHP、MySQL、PDO 事务 - 调用 commit() 后是否可以使用 rollBack()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37363417/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com