try
{
$con->beginTransaction();
$this->doSave($con);
$con->commit();
}
catch (Exception $e)
{
$con->rollBack();
throw $e;
}
上面的代码是处理交易的标准方法,
但我的问题是:如果$con->rollBack()
也失败了怎么办?
这可能导致数据库锁定,对吧?如果是这样,最好的方法是什么?
答案 0 :(得分:4)
使用事务时,基本思路是在调用commit
之前,实际上不会将任何内容永久写入数据库。
有几种情况:
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引擎,该引擎速度更快且不事务性。您需要做的就是在创建数据库时更改存储引擎。