PHP中的数据库事务回滚处理

时间:2010-03-02 21:13:14

标签: php database transactions

try
{
  $con->beginTransaction();

  $this->doSave($con);

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

  throw $e;
}

上面的代码是处理交易的标准方法,

但我的问题是:如果$con->rollBack()也失败了怎么办?

这可能导致数据库锁定,对吧?如果是这样,最好的方法是什么?

3 个答案:

答案 0 :(得分:4)

使用事务时,基本思路是在调用commit之前,实际上不会将任何内容永久写入数据库。

有几种情况:

  • 如果你:
    • 开始交易
    • 执行一些查询
    • 回滚
    • 然后回滚查询;这意味着他们的结果不会写入数据库。
  • 如果你:
    • 开始交易
    • 执行一些查询
    • disconnect (如果你的PHP脚本结束会发生这种情况 - 例如,由于致命错误或die
    • 然后,查询没有被提交 - 这意味着他们没有被写入数据库;这意味着它与rollback
    • 相同


为简单起见:从begin transaction开始,在发送commit之前,不会将任何内容永久写入数据库。如果没有提交...没有永久写入,并且当您的PHP脚本与数据库断开连接时,数据库“取消”该PHP脚本未提交的内容。

当然,如果您使用除PHP以外的其他东西来连接到您的数据库,那就完全一样了 - 比如命令行MySQL客户端。

答案 1 :(得分:1)

MySQL通过回滚事务本身来处理错误情况。

  

回滚可能是一个缓慢的操作,可能会在没有用户明确要求的情况下隐式发生(例如,发生错误时)。

MySQL documentation涵盖了您的“假如案例”

  

如果已禁用自动提交的会话在没有显式提交最终事务的情况下结束,则MySQL将回滚该事务。

此外:

  

提交和回滚都会释放在当前事务期间设置的所有InnoDB锁。

编辑:我为您提议的情况设置了测试。使用带有MySQL 5的innoDB表。

$db = new DB();
$db->beginTransaction();
$db->exec("INSERT INTO `table` (`val`) VALUES('commit?')");
sleep(30);
$db->commit();

这正如我在下面的评论中描述的那样。如果允许完成,则事务在30秒后提交到表中。

如果我在允许脚本完成之前终止该脚本,则会回滚事务并使表保持干净状态 - 正如预期的那样。

答案 2 :(得分:0)

使用事务数据库引擎,例如 InnoDB 。这将保证在写入期间查询失败时的数据完整性。 MySQL默认使用MyISAM引擎,该引擎速度更快且事务性。您需要做的就是在创建数据库时更改存储引擎。