Listening to the Words

MYSQL:1213 Deadlock问题

最近上线的新项目出现了一点问题:

 'file' => '/var/www/html/hewai/thinkphp/library/think/db/Connection.php:764',
  'message' => 'SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction',
  'trace' => '#0 /var/www/html/hewai/thinkphp/library/think/db/Connection.php(1157): think\\db\\Connection->execute(\'UPDATE `user_da...\', Array, Object(think\\db\\Query))
#1 /var/www/html/hewai/thinkphp/library/think/db/Query.php(2903): think\\db\\Connection->update(Object(think\\db\\Query))
#2 /var/www/html/hewai/application/api/service/task/Mission.php(230): think\\db\\Query->update(Array)
#3 /var/www/html/hewai/application/api/service/task/TaskDailyEvent.php(165): app\\api\\service\\task\\Mission::update(73685021, 20032, Array)
#4 /var/www/html/hewai/application/api/service/task/TaskDailyEvent.php(132): app\\api\\service\\task\\TaskDailyEvent->update(73685021, 20032, 0)
#5 /var/www/html/hewai/application/api/service/task/DistributorTask.php(156): app\\api\\service\\task\\TaskDailyEvent->determine(-1, Array)

SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction

1213数据库经典的死锁场景,参看了这篇文章后反思自己的语句问题.

https://www.jianshu.com/p/6049b046e7b4?from=groupmessage

但是很遗憾,我的语句只是一个简单的update的语句,而且业务里只有这一个类型的更新别且连insert和delete都没有.

然后我开始反思表结构,我设置了三个索引,于是我explain下update语句发现,type 类型是index_merge 索引合并,在查看extra后发现使用了using intersect,猜想是不是这个index_merge导致的间隙锁呢?

于是google一下:索引类型index_merge导致mysql死锁;

index_merge引发的死锁排查:https://www.cnblogs.com/cchust/p/6464188.html

问题的源头就是index_merge,死锁的原因也很普通,两个事务加锁顺序不同,并存在相互等待的情况

解决方案

最后将两个索引合并成复合索引,使mysql不在产生index_merge的优化项目

如何避免死锁

下面介绍几个简单的原则,有助于减少死锁的发生。

1) 尽量按顺序加锁,从源头避免死锁
2)选择合适的隔离级别,隔离级别越高,并发冲突越激烈,实际场景Read-Committed就够用了
3)避免使用大事务,根据二段锁原则,只有事务结束(提交或回滚)才会释放锁,持有的锁越多,可能导致的冲突越大
4)为表添加合适的索引,避免走不到索引导致对每条记录都加锁

点赞