mysql报错:Deadlock found when trying to get lock; try restarting transaction的解决方法

 更新时间:2017年07月12日 09:37:30   作者:都市烟火  
这篇文章主要给大家介绍了关于mysql出现报错:Deadlock found when trying to get lock; try restarting transaction的解决方法,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。

发现问题

最近在补以前数据的时候程序突然报如下错误:

[2017-02-10 13:12:06.678] [INFO] mysqlLog - update tbl_playerdata_error: { [Error: ER_LOCK_DEADLOCK: Deadlock found when trying to get lock; try restarting transaction]
 code: 'ER_LOCK_DEADLOCK',
 errno: 1213,
 sqlState: '40001',
 index: 0 }

一看就是mysql出现了死锁问题,其实上面跑的程序在测试服跑了好久都没什么问题,为什么在正式服上会出现mysql的死锁问题呢,第一反应是不是数据量太大(3百多万条),可是也不可能啊,再说死锁和这些有什么鸡毛的关系,看来要好好解决下了。

问题分析

我的分析是:由于现在处理的是正式服的数据,而正式服还有许多用户在操作,应该是在用户查询,或者是其他操作的时候,和我这边的数据更新产生了死锁(首先说明使用的是:InnoDB存储引擎。由于用户那边的查询或者其他操作锁定了我需要的资源,而我这边更新也锁定了用户操作的一部分资源,两边都等着对方释放资源,从而导致死锁)。

解决方法

知道错误code之后,先来查看mysql的说明,关于上面的 Error: 1213 SQLSTATE: 40001,参见:Server Error Codes and Messages

Message: Deadlock found when trying to get lock; try restarting transaction

InnoDB reports this error when a transaction encounters a deadlock and is automatically rolled back so that your application can take corrective action. To recover from this error, run all the operations in this transaction again. A deadlock occurs when requests for locks arrive in inconsistent order between transactions. The transaction that was rolled back released all its locks, and the other transaction can now get all the locks it requested. Thus, when you re-run the transaction that was rolled back, it might have to wait for other transactions to complete, but typically the deadlock does not recur. If you encounter frequent deadlocks, make the sequence of locking operations (LOCK TABLES, SELECT ... FOR UPDATE, and so on) consistent between the different transactions or applications that experience the issue. See Section 14.8.5, “Deadlocks in InnoDB” for details.

上面有两句:

To recover from this error, run all the operations in this transaction again<br><br>If you encounter frequent deadlocks, make the sequence of locking operations (<code class="literal">LOCK TABLES</code>, <code class="literal">SELECT ... FOR UPDATE</code>, and so on) <br>consistent between the different transactions or applications that experience the issue 

这两句也就道出了处理死锁的方法了,我就是在死锁错误发生的时候,使用定时器再重新做一次更新操作,这样就避免了上面出现的问题。

另外,参考了stack overflow上面一个回答:http://stackoverflow.com/questions/2332768/how-to-avoid-mysql-deadlock-found-when-trying-to-get-lock-try-restarting-trans

One easy trick that can help with most deadlocks is sorting the operations in a specific order.

You get a deadlock when two transactions are trying to lock two locks at opposite orders, ie:

connection 1: locks key(1), locks key(2);
connection 2: locks key(2), locks key(1);
If both run at the same time, connection 1 will lock key(1), connection 2 will lock key(2) and each connection will wait for the other to release the key -> deadlock.

Now, if you changed your queries such that the connections would lock the keys at the same order, ie:

connection 1: locks key(1), locks key(2);
connection 2: locks key(1), locks key(2);
it will be impossible to get a deadlock.

So this is what I suggest:

Make sure you have no other queries that lock access more than one key at a time except for the delete statement. if you do (and I suspect you do), order their WHERE in (k1,k2,..kn) in ascending order.
Fix your delete statement to work in ascending order:
Change

DELETE FROM onlineusers WHERE datetime <= now() - INTERVAL 900 SECOND
To

DELETE FROM onlineusers WHERE id IN (SELECT id FROM onlineusers
 WHERE datetime <= now() - INTERVAL 900 SECOND order by id) u;
Another thing to keep in mind is that mysql documentation suggest that in case of a deadlock the client should retry automatically. you can add this logic to your client code. (Say, 3 retries on this particular error before giving up).

参考:http://blog.sina.com.cn/s/blog_4acbd39c01014gsq.html

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • 解析SQL Server 视图、数据库快照

    解析SQL Server 视图、数据库快照

    在程序开发过程中,任何一个项目都离不开数据库,这篇文章给大家详细介绍SQL Server 视图、数据库快照相关内容,需要的朋友可以参考下
    2015-08-08
  • MySQL [Warning] TIMESTAMP with implicit DEFAULT value is deprecated(报错信息解决)

    MySQL [Warning] TIMESTAMP with implicit&

    本文介绍了MySQL中常见的报错信息及其解决方法,主要包括TIMESTAMP with implicit DEFAULT value is deprecated、ERROR_FOR_DIVISION_BY_ZERO和NO_ZERO_DATE/NO_ZERO_IN_DATE等报错信息,以及对应的配置文件设置和sql_mode修改方法,感兴趣的朋友一起看看吧
    2025-02-02
  • mysql的case when字段为空,null的问题

    mysql的case when字段为空,null的问题

    这篇文章主要介绍了mysql的case when字段为空,null的问题。具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • 深入理解mysql各种锁

    深入理解mysql各种锁

    大家好,本篇文章主要讲的是深入理解mysql各种锁,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • MySQL中使用auto_increment修改初始值和步长

    MySQL中使用auto_increment修改初始值和步长

    本文主要介绍了MySQL中使用auto_increment修改初始值和步长,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05
  • MySQL锁等待超时问题的原因和解决方案(Lock wait timeout exceeded; try restarting transaction)

    MySQL锁等待超时问题的原因和解决方案(Lock wait timeout exceed

    在数据库开发和管理中,锁等待超时是一个常见而棘手的问题,对于使用 MySQL 的应用程序,尤其是采用 InnoDB 存储引擎的场景,这一问题更是屡见不鲜,本文给大家介绍了MySQL锁等待超时问题的原因和解决方案,需要的朋友可以参考下
    2024-11-11
  • MySQL8.0.24版本Release Note的一些改进点

    MySQL8.0.24版本Release Note的一些改进点

    这篇文章主要介绍了MySQL8.0.24版本Release Note的一些改进点,帮助大家更好的对新版本的MySQL进行测试使用,感兴趣的朋友可以了解下
    2021-04-04
  • mysql安装配置方法图文教程(CentOS7)

    mysql安装配置方法图文教程(CentOS7)

    这篇文章主要为大家详细介绍了centos7下mysql安装配置方法图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • window环境下使用VScode连接虚拟机MySQL方法

    window环境下使用VScode连接虚拟机MySQL方法

    这篇文章主要介绍了window环境下使用VScode连接虚拟机MySQL方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • MySQL是如何实现主备同步

    MySQL是如何实现主备同步

    这篇文章主要介绍了MySQL是如何实现主备同步的,帮助大家更好的理解和使用MySQL数据库,感兴趣的朋友可以了解下
    2020-12-12

最新评论