问题现象:一张任务数据表,创建记录后,会根据业务处理完成后,更新状态为成功或失败,但是经常出现错误日志报该表出现死锁,表索引如下:
常规排查思路:首先从业务代码逐步排查,发现该表除了创建记录和查下,只有更新状态可能会出现行锁,但更新记录虽然有多线程可能会并发,但是同一个task_id理论上只会被同一个协程进行处理,理论山上不应该出现死锁。
问题分析:从业务代码看无法得出可能的原因,找DBA获取了数据库日志后仔细分析,发现该update语句,实际上并未用到对应的task_id的索引,而是用到了status+business_typ的索引,并且可能锁住了多条记录。
结论总结:由于索引非预期的task_id,导致多个协程并发处理的时候,就有一定概率互相锁住了不同的记录,导致互相等待出现死锁,而这类业务一般业务量不是太大,所以出现概率比较小,而偶尔有一波业务高峰,当更新语句较多时,才会概率性的刚才满足了死锁条件。
问题警示:后续对于有多个索引的表,并且有多协程并发操作的,都需要仔细使用”解释执行计划“确认一下各个索引的命中情况,避免再次出现该类问题。