@胡图图,页锁就是行锁,因为你使用的引擎在查询时可能不使用行锁。页锁是一次锁定多行,但不是整个表。
以MySQL为例:
https://www.cnblogs.com/jpfss/p/8890250.html
看起来每个圈都是一个相关SQL语句。所以你的死锁看起来有4个SQL语句参与其中。
把每个SQL语句的具体内容都列出来再分析。
如果语句是执行一个存储过程,请查看存储过程的语句,否则只显示一个exec 某某某
啥也说明不了。
@胡图图,哦还有一个方法,就是自己设一个加锁超时时间。比如设为1秒还没锁定好就放弃,回滚事务,抛出异常,然后程序自行重试。快速失败总比死锁需要手动解除更好。
https://blog.csdn.net/weixin_30715523/article/details/96814548
@胡图图,由于10楼的特性(单个查询语句自己就能把自己弄死锁),想要完全避免死锁似乎是不可能的。那么11楼可能就是较好的解决方法了,可以在不伤害性能的情况下保证死锁对业务没有影响。在第一次加锁失败事务回滚后,只要把之前执行的SQL语句再执行一次,可能就不会死锁了。死锁通常只是偶然事件,不会每次都运气如此不好。
当然,如果死锁频率非常高,就要考虑数据库并发是否太大,开始超过服务器处理能力,或者SQL语句设计不合理了。此时应该考虑使用外部缓存,不要把所有压力都堆到数据库上。
还有,减少关联查询(多表查询)的数量,把要关联的字段都提前“传播”(复制)到最终要查询的表上。比如虎绿林的版块访问权限字段,如果只存在于版块表,那展示帖子列表时就需要关联查询,性能非常差。搜索用户回复时性能就更差了,因为要进行两层关联查询(找到回复所在帖子,再找到帖子所在版块,再看权限)。
但是,如果提前把权限“传播”到帖子和回复表,并且用合理的机制保证三者同步,那查询时就只需要看各自表中的条件即可,不仅消除了关联查询,还可以提前做索引。所以虎绿林添加版块访问权限几乎没有给论坛性能带来负面影响。
而在我想到“传播权限”这个优化方法之前,帖子列表加载非常慢(秒级),回复搜索则完全不可用(分钟级)……
@胡图图,该更新语句并发执行时,可能两个进程各自持有表中部分行的锁,它们都无法获取表中对方进程持有的行锁,导致谁也无法完成更新。
此时可以考虑先给整个表上锁,然后再执行update。
https://blog.csdn.net/bobozai86/article/details/89915362