如果一个查询等待其他查询持有的锁,会如何发生死锁



我面临以下例外:

com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction

我能说的是,我有多个线程并行地在同一个表上执行查询。但我不明白为什么会出现这种异常。因为如果一个查询锁定了一个表,那么另一个线程中的相同查询(或同一表上的其他查询)将等待锁定。死锁是如何产生的?

我用不同的话重复,我理解异常,但是我不理解的是,一个查询正在等待另一个查询,另一个查询应该执行,离开锁,而等待查询可以获得锁,为什么死锁?

如果有人想查看实际的查询(这些查询在多个线程中以与这里打印的相同的顺序执行,没有任何事务):

UPDATE daily_stats, account, campaign SET campaign_messages_cost = campaign_messages_cost + (IF(current_free_sms >= ?, campaign.campaign_cost, campaign.campaign_cost + (account.sms_charging_rate * ? ))), campaign_messages_delivered_count = campaign_messages_delivered_count + 1 WHERE daily_stats_id = ? AND campaign.id = ? AND daily_stats.account_id = account.id
update account a JOIN campaign b ON a.id = b.account_id set campaign_cost = IF(current_free_sms >= ?, campaign_cost, campaign_cost + (a.sms_charging_rate * ? )), delivered_count = delivered_count + ?, credit = IF(current_free_sms >= ?, credit, credit - (a.sms_charging_rate * ?)), current_free_sms = IF (current_free_sms >= ?, current_free_sms - ?, current_free_sms) where b.id = ?

MySQL将任何查询语句视为事务(至少在使用默认InnoDB引擎时),但是如果@@autocommit变量设置为1(默认),则所有语句都立即自动提交,有效地隐藏了事务的发生。这可以解释"deadlock found"错误,尽管没有开始/提交/回滚,尽管错误消息的"回滚"部分有点神秘,而且我以前没有见过。

mysql建议的处理死锁的方法是将你的查询结构化以最小化问题,并且在它们发生时编写处理它们的代码-因为它们会在像你这样的软件中出现。我的方法简单而有效:睡眠500毫秒,然后重试。我很少看到连续两次以上的重试,在处理相当高负载的系统上(尽管是在公司环境中)。

你还应该看看mysql关于如何处理死锁的建议

最新更新