1

我有像这样工作的事务应用程序:

try {
     $db->begin();
     increaseNumber();
     $db->commit();
} catch(Exception $e) {
     $db->rollback();
}

然后在 increaseNumber() 里面我会有一个像这样的查询,这是唯一适用于这个表的函数:

// I use FOR UPDATE so that nobody else can read this table until its been updated
$result = $db->select("SELECT item1
FROM units
WHERE id = '{$id}'
FOR UPDATE");

$result = $db->update("UPDATE units SET item1 = item1 + 1
WHERE id = '{$id}'");

一切都包含在事务中,但最近我一直在处理一些非常慢的查询,并且我的应用程序中有很多并发性,所以我无法确保查询是以特定顺序运行的。

死锁会导致 ACID 事务中断吗?我有一个添加某些内容的函数,然后是另一个删除它的函数,但是当我遇到死锁时,我发现数据完全不同步,就像忽略了事务一样。

这一定会发生还是有其他问题?

谢谢,多米尼克

4

2 回答 2

2

好吧,如果一个事务遇到一个没有释放的锁(来自另一个事务),它会在超时后失败。我相信默认值为 30 秒。如果有人在数据库上使用任何 3rd 方应用程序,您应该注意。我知道一个事实,例如,SQL Manager 2007 不会释放InnoDB 上的锁,除非您断开与数据库的连接(有时它只需要一个 Commit Transaction ......好吧,一切),这会导致很多查询在之后失败暂停。当然,如果您的事务是 ACID 兼容的,它应该以全有或全无的方式执行。仅当您在事务之间中断数据时,它才会中断。

您可以尝试延长超时时间,但 30 秒的锁定可能意味着一些更深层次的问题。当然,这取决于您使用的存储引擎(通过MySQL标签和事务,我假设为 InnoDB)。

您还可以尝试打开查询分析,以查看是否有任何查询运行了很长时间。请注意,它当然会降低性能,因此它可能不是生产解决方案。

于 2011-07-13T08:07:02.493 回答
1

ACID 中的 A 代表 Atomic,因此没有死锁不能使 ACID 事务中断——相反,它不会像全有或全无一样发生。

更有可能的是,如果您的数据不一致,您的应用程序在逻辑单个事务中执行多个“事务”,例如:用户创建和帐户 (transaction-begin..-commit),用户设置密码 (transaction-begin.. .-deadlock..-rollback) 你的应用程序忽略了错误并继续,现在你的数据库留下了一个创建的用户并且没有密码。

在您的应用程序中查看应用程序除了回滚之外还在做什么,以及逻辑上是否有多个部分来构建一致的数据。

于 2011-07-13T08:09:49.950 回答