SQL死锁原因

SQL死锁指在多用户并发访问数据库时,由于竞争锁资源而导致的一种相互等待的状态,使得程序无法继续执行的情况。SQL死锁的原因可以归结为以下几种情况:

1.资源争夺
多个事务同时访问同一资源,例如同一数据行时,会发生数据行锁定。如果没有正确的释放锁导致数据行锁定被占用,其他事务无法访问该资源,就会出现死锁。

2.锁表顺序不同
如果事务A按照表A->表B的顺序锁定数据行,但是事务B按照表B->表A的顺序锁定数据行,就有可能导致死锁。

3.事务长时间运行
如果一个事务持有一个锁,并长时间运行,其他事务可能会发生死锁。
==================================================================================

死锁产生的原因:
①不可剥夺(只能由占有资源的进程释放)
②循环等待(每个进程在等待其他进程释放,而其他进程也在等待)
③互斥条件 (一个资源只能同时被一个进程使用)
④请求与保持(申请新资源,并还不释放已占有的)

sql死锁
死锁发生的主要原因是这两个事务对表的锁定顺序不一致,先拿到一把锁的事务等待另一把锁,而那一把锁正被另一个事务持有,形成闭环等待。
①同一个表中:在一个事务中对同一表进行两次或多次操作,并且在多线程的情况下有多个这样的事务,这可能会导致死锁。
②不同表中:两个事务操作表的顺序不同,出现锁表交叉循环,导致死锁。

解决办法: (本质:快速筛选或高效处理、以此减少锁冲突)
①大事务拆成小事务,尽可能缩小事务范围
大事务:将多个操作放在一个事务中执行
优点:这样可以减少事务的提交和回滚次数,提高性能。

缺点:如果事务过大,涉及到的数据量多,会增加事务持有锁的时间,增加死锁的风险。

小事务:将多个操作分成多个小事务,
优点:每个小事务只涉及少量的数据,尽快释放锁资源。这样可以减少事务持有锁的时间,降低死锁的风险

②业务中存在更新前和更新后一模一样的不再执行更新
场景:通过运维拉去mysql日志,查询发现,下面2事务,对表ps_option_value666进行更新操作,查询数据库发现,要更新的数据和想更新的数据,一模一样!

解决方案:在代码层面检查对象内容如果一样,就不更新了!

3、 调整表修改的顺序
按照同一顺序获取多个锁,释放锁时反序释放。这可以避免不同事务交叉锁定导致死锁

4. 索引不当导致的死锁
为什么建索引能有效避免死锁呢?
1.为了减少事务持有锁的时间,以此来降低死锁的可能性。

2、避免不同事务对相同的数据行进行锁定,从而减少锁竞争与死锁。(如:对username字段创建普通索引,对email字段创建唯一索引)

5、降低并发
如果性能允许,自然是单个线程,相当于单个事务在执行,那肯定没死锁!这个就看代码性能和业务允许不允许了

6、重试机制
如果发生死锁,重试可能就好了哇

 

posted @ 2023-08-15 16:50  walkersss  阅读(199)  评论(0编辑  收藏  举报