关于数据库死锁的疑问

@Ta 01-13 19:57发布,01-13 19:57修改 424点击
最近碰到一个数据库,执行插入时经常遇到死锁,然后被杀掉进程的情况。
update语句对同一个表太多也会造成死锁?
怎么确认这是如何发生的死锁
回复列表(17)
  • @Ta / 01-13 21:57

    @胡图图,该更新语句并发执行时,可能两个进程各自持有表中部分行的锁,它们都无法获取表中对方进程持有的行锁,导致谁也无法完成更新。

    此时可以考虑先给整个表上锁,然后再执行update。

    https://blog.csdn.net/bobozai86/article/details/89915362

  • @Ta / 01-14 08:25
    @老虎会游泳,在死锁图里显示的是页锁,不是行锁
  • @Ta / 01-14 08:26
    IMG_20220114_082546.jpg
  • @Ta / 01-14 13:44
    @胡图图,你这个操作看起来也不是很频繁  都发生这种事?
  • @Ta / 01-14 14:49

    @胡图图,页锁就是行锁,因为你使用的引擎在查询时可能不使用行锁。页锁是一次锁定多行,但不是整个表。

    以MySQL为例:

    https://www.cnblogs.com/jpfss/p/8890250.html

    图片.png
  • @Ta / 01-14 14:57

    @胡图图,如果你使用SQL Server,那么可能会存在行锁、页锁、表锁。可以把页锁理解为多行同时锁定,死锁情况和行锁类似。

    死锁分析教程:
    https://www.cnblogs.com/m15921285681/p/4005355.html

  • @Ta / 01-14 14:53
    图片.png
  • @Ta / 01-14 14:54
    图片.png
  • @Ta / 01-14 14:56

    看起来每个圈都是一个相关SQL语句。所以你的死锁看起来有4个SQL语句参与其中。
    把每个SQL语句的具体内容都列出来再分析。
    如果语句是执行一个存储过程,请查看存储过程的语句,否则只显示一个exec 某某某啥也说明不了。

  • @Ta / 01-14 14:59

    @胡图图,这个有趣的图表示,SQL Server里单个查询自身也可能会死锁,因为它会尝试多线程运行,然后各个线程互相死锁……

    这应该被认为是SQL Server的设计缺陷!

    解决方法可能只有一个,“指定让它单线程运行”……

    图片.png
  • @Ta / 01-14 15:04

    @胡图图,哦还有一个方法,就是自己设一个加锁超时时间。比如设为1秒还没锁定好就放弃,回滚事务,抛出异常,然后程序自行重试。快速失败总比死锁需要手动解除更好。

    https://blog.csdn.net/weixin_30715523/article/details/96814548

  • @Ta / 01-14 15:20

    @胡图图,由于10楼的特性(单个查询语句自己就能把自己弄死锁),想要完全避免死锁似乎是不可能的。那么11楼可能就是较好的解决方法了,可以在不伤害性能的情况下保证死锁对业务没有影响。在第一次加锁失败事务回滚后,只要把之前执行的SQL语句再执行一次,可能就不会死锁了。死锁通常只是偶然事件,不会每次都运气如此不好。

    当然,如果死锁频率非常高,就要考虑数据库并发是否太大,开始超过服务器处理能力,或者SQL语句设计不合理了。此时应该考虑使用外部缓存,不要把所有压力都堆到数据库上。

    还有,减少关联查询(多表查询)的数量,把要关联的字段都提前“传播”(复制)到最终要查询的表上。比如虎绿林的版块访问权限字段,如果只存在于版块表,那展示帖子列表时就需要关联查询,性能非常差。搜索用户回复时性能就更差了,因为要进行两层关联查询(找到回复所在帖子,再找到帖子所在版块,再看权限)。

    但是,如果提前把权限“传播”到帖子和回复表,并且用合理的机制保证三者同步,那查询时就只需要看各自表中的条件即可,不仅消除了关联查询,还可以提前做索引。所以虎绿林添加版块访问权限几乎没有给论坛性能带来负面影响。

    而在我想到“传播权限”这个优化方法之前,帖子列表加载非常慢(秒级),回复搜索则完全不可用(分钟级)……

  • @Ta / 01-14 23:59
    @老虎会游泳,说不定真的是并发太多了?他触发器一个套一个/捂脸
  • @Ta / 01-14 23:59

    @胡图图,触发器啊,把完全有可能

  • @Ta / 01-15 00:52
    @老虎会游泳,那我该如何解决这个问题,升级硬件行吗?
  • @Ta / 01-15 01:12

    @胡图图任选。不,建议使用方案4,设置加锁超时时间。

    • 在更新前对整个表进行加锁。

    • 删除触发器,通过执行更新语句维持表间关系。

    • 在触发器地狱中寻找线索,祈祷能找到引发问题的触发器规则,然后进行修改。

  • @Ta / 01-15 01:11

    @胡图图,我忘记了最重要的一条:

添加新回复
回复需要登录