【发布时间】:2014-03-26 18:22:45
【问题描述】:
在 PHP 中,使用内置的 PDO 数据库抽象层,这样的代码并不少见:
function B()
{
$db = new PDO(...);
$db->beginTransaction();
// do something
$db->commit();
}
function A()
{
$db = new PDO(...);
$db->beginTransaction();
// do something
B();
$db->commit();
}
请注意,A 和 B 都有自己的数据库连接,并且都启动事务,并且 A 调用 B。结果是,在某些情况下(即 B 正在做的事情依赖于 A 所做的事情),这种编码模式将导致死锁。
例如,假设我们有表 Foo 和 Bar。 Foo 包含引用 Bar 的外键,并设置为 ON DELETE CASCADE。假设函数A 更新Foo 以更改该外键字段的值,然后函数B 删除Bar 中现在未使用的记录。因为A 的事务尚未提交,B 中的 SQL 将等待它,即使在 B 返回之前它永远不会提交。
有没有办法在不将数据库对象传递给每个函数的情况下解决这个问题?看起来 PDO 本身应该能够通过简单地跟踪嵌套事务来正确处理这个问题。
我已经尝试了 cmets here 中的解决方案,其中 PDO 被子类化以进行嵌套事务计数,但它似乎并没有真正起作用 - 我假设因为 A() 和 @987654338 中的 $db 对象@ 不是同一个实例,所以它们彼此不知道,并且任一实例中的计数器的值都不正确。
【问题讨论】:
-
“这并不罕见”?真的吗?
-
当然,为什么不呢?这似乎是最明显的实现。例如,PHP docs 似乎正是这样做的 - 请参阅“示例 #2”。你会建议什么?
标签: php transactions