线上碰到存储过程死锁问题了,开始以为非主键查询 for update 会导致表锁,后来经过测试 innodb下for update索引生效的情况下 根据索引字段查询是行级锁,会将整个结果集进行上锁,直到事务结束。
错误地方进行一些修正,一般情况的确是将索引的结果集进行上锁,但是由于表过大的情况,mysql为了性能自动优化将索引附近的结果集全部进行上锁。
具体实验过程可以看https://blog.csdn.net/qq_31975227/article/details/103710018,自己做一遍也能实验出来。
但是存储过程死锁的问题还是没有解决,不过该存储过程只是进行内存统计数据的落库,所以不应该上锁。虽然程序是node调用,但是也不会出现执行顺序问题,如果出现了执行顺序问题加了行级锁也是没有用的,又不是在源数据进行加减等计算操作,计算操作都在内存完成了,最后只进行了落库操作。(来至个人的吐槽,我没办法说法领导,后来和领导沟通说明白了问题)
死锁的问题通过分析死锁日志文件解决了,由于上面一块错误的认识。一直认为两个非唯一索引可以命中单条记录,其实mysql为了性能命中了多条。
一个简单的update语句,update ? where id1=1 and id2=2 id1和id2 都是非唯一索引,这时有的语句会对因为优化导致上锁其他索引周边的数据条目,这时他会等待内建唯一索引的锁,而同样的语句会对内建唯一索引加锁,等待id1 或者id2的锁,出现同一条语句回环等待锁的释放,导致死锁发生。
以后还是需要多看一些数据库方面的书籍,对原理性知识了解的更多一些。