死锁和超时会破坏ACID交易

时间:2011-07-13 07:57:13

标签: php mysql transactions acid database-concurrency

我的交易应用程序就像这样:

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交易中断吗?我有一个函数添加一些东西,然后另一个删除它,但是当我有死锁时,我发现数据完全不同步,就像事务被忽略一样。

这是否会发生或其他问题?

谢谢,Dominic

2 个答案:

答案 0 :(得分:2)

好吧,如果一个事务遇到一个没有释放的锁(来自另一个事务),它将在超时后失败。我相信默认值是30秒。如果有人在数据库上使用任何第三方应用程序,您应该记下。我知道一个事实,例如, SQL Manager 2007 不会在InnoDB上发布锁,除非您与数据库断开连接(有时它只需要一个提交事务...好吧,一切),这会导致很多查询在超时后失败。当然,如果您的交易符合ACID,它应该全有或全无。只有在事务之间中断数据时它才会中断。

您可以尝试延长超时,但30秒锁可能意味着更深层次的问题。当然,这取决于您使用的存储引擎(MySQL标记和我假设InnoDB的交易。)

您还可以尝试启用query profiling,查看是否有任何查询运行了一段荒谬的时间。请注意,它确实会降低性能,因此它可能不是生产解决方案。

答案 1 :(得分:1)

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

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

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