死锁和超时会破坏 ACID 事务
我有一个像这样工作的事务应用程序:
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 事务中断吗?我有一个函数添加一些内容,然后另一个函数删除它,但是当我出现死锁时,我发现数据完全不同步,就像事务被忽略一样。
这是一定会发生的还是有其他问题?
谢谢,多米尼克
I've got transactional application that works like so:
try {
$db->begin();
increaseNumber();
$db->commit();
} catch(Exception $e) {
$db->rollback();
}
And then inside the increaseNumber() I'll have a query like so, which is the only function that works with this table:
// 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}'");
Everything is wrapped in a transaction but lately I've been dealing with some pretty slow queries and there's a lot of concurrency going on in my application so I can't really make sure that queries are to be run in a specific order.
Can deadlocks cause ACID transactions to break? I have one function that adds something and then another that removes it but when I have deadlocks then I find the data is completely out of sync like the transactions were ignored.
Is this bound to happen or is something else wrong?
Thanks, Dominic
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好吧,如果一个事务遇到一个未释放的锁(来自另一个事务),那么它会在超时后失败。我相信默认是 30 秒。您应该记下是否有人在数据库上使用任何第三方应用程序。我知道一个事实,例如,SQL Manager 2007 不会释放 InnoDB 上的锁,除非您与数据库断开连接(有时它只需要在...上提交事务)好吧,一切),这会导致很多查询在超时后失败。当然,如果您的事务符合 ACID,那么它应该以全有或全无的方式执行。仅当您破坏事务之间的数据时,它才会破坏。
您可以尝试延长超时时间,但 30 秒的锁定可能意味着一些更深层次的问题。当然,这取决于您使用的存储引擎(通过
MySQL
标记和事务,我假设是 InnoDB)。您还可以尝试打开查询分析来查看如果任何查询运行了很长的时间。请注意,它当然会降低性能,因此它可能不是生产解决方案。
Well, if a transaction runs into a lock (from another transaction) that doesn't release, it'll fail after timeout. I believe the default is 30 seconds. You should make note if anyone is using any 3rd party applications on the database. I know for a fact that, for example, SQL Manager 2007 does not release locks on InnoDB unless you disconnect from database (sometimes it only takes a Commit Transaction on ... well, everything), which causes a lot of queries to fail after timeout. Of course, if your transactions are ACID-compliant, it should execute in all-or-nothing. It will break only if you break data between transactions.
You can try extending the timeout, but a 30 second lock might imply some deeper problems. It depends, of course, on what storage engine you're using (by
MySQL
tag and transactions I assumed InnoDB).You can also try and turn on query profiling to see if any queries run for a ridiculous amount of time. Just note that it does, of course, decrease performance, so it may not be a production solution.
ACID 中的 A 代表“原子”,因此任何死锁都不会导致 ACID 事务中断——相反,它不会像“全有或全无”那样发生。
更有可能的是,如果数据不一致,则应用程序正在逻辑单个事务中执行多个“事务”,例如:用户创建和帐户(事务开始..-提交)、用户设置密码(事务开始.. .-deadlock..-rollback)您的应用程序忽略了错误并继续,现在您的数据库只剩下创建的用户且没有密码。
查看您的应用程序中除了回滚之外该应用程序还在执行哪些操作,以及逻辑上是否有多个部分来构建一致的数据。
A in ACID stands for Atomic, so no deadlocks cannot make an ACID transaction break -- Rather it will make it not happen like in all-or-nothing.
More likely, if you inconsistent data, you application is doing multiple "transactions" in what is a logical single transaction, like: user creates and account (transaction-begin..-commit), user sets a password (transaction-begin...-deadlock..-rollback) your application ignored the error and continues, and now your database is left with a user created and no password.
Look in your application as what else the application is doing besides the rollback, and logically whether there is multiple parts to the build up of the consistent data.