死锁分析

死锁起因

测试组提交bug,说在集群执行analyze时报错,不稳定复现,语句大致如下: create table xxx(col1 int, col2 …); insert into xxx values(1, xxx …); insert into xxx values(1, xxx …); insert into xxx values(1, xxx …); insert into xxx values(1, xxx …); insert into xxx select * from xxx; insert into xxx select * from xxx; insert into xxx select * from xxx; insert into xxx select * from xxx; analyze xxx;–执行报错

阶段一

集群的同事给力的迅速分析出原因,发现在做analyze时x节点报错(Error, systable_getnext时出错,在xxx对象上发生死锁),集群为保证一致性,认为事务整体失败,报错回滚。由此,问题转化成,为什么x节点执行analyze时会发生死锁。

阶段二

分析节点x日志,当session 1报错时,附近对该表的操作有以下三种:

阶段三

同事动作很快,说是更简单,使用导入工具导入的过程中,做analyze就会比较稳定的复现。 尴尬了,这与预期的设想不一致,怀疑是另外一个bug,手里工作比较急,暂时没时间处理,只好让同事代为保管环境,打算稍后分析。 幸运的是,开始分析时,发现数据的导入已经结束,而且包级的复制也已经结束,但此时依然可以较稳定的复现死锁问题。 不幸的是,发生的条件居然是一直认为不可能的包级复制自更新和analyze之间发生死锁。 即: 事务1,进行analyze。 事务2,进行包级复制自更新。 执行一段时间后,analyze报错,在xxx对象上发生死锁。

阶段四

那么究竟是什么原因呢?首先,共享锁和拍他锁一定是互斥的,且事务1analyze先做,一定能先拿到锁,从而阻塞事务2加排他锁,然后应该一直等待事务1结束事务2才可以开始做,怎么会发生事务1申请锁时被事务2阻塞? 初步怀疑,事务1拿到表级锁后,在运行一段时间后释放掉了,持有包级锁,然后事务2拿到表级锁,在获取包级锁时需要等待事务1,事务1在运行一段时间后,发现需要更新一些信息,因此再去拿表级锁时,等待事务2.形成环,死锁。 按照这个思路分析,仅需要了解事务1(analyze)什么时间放掉共享锁,又是为什么放掉共享锁,事情应该就可以解决了,然而,在调试过程中,发现和预期的不一致,在某个时间点,两个事务均拿到了表级锁,这怎么可能?

阶段五

根据动态视图的展示,发现的确两个事务均持有表级锁,但并不是预期的事务1(analyze)持有共享锁,事务2持有排他锁。 而是事务1持有共享锁,更新锁(与共享锁不互斥,与拍他锁互斥)。 事务2(包级复制自更新)持有的居然是预期之外的共享锁。 那么,难道是锁加错了?

阶段六

经过几次调试,发现,事务1在更新加排他锁之前,调用的系统表扫描接口中加了更新锁(与共享锁不互斥,与拍他锁互斥),而事务2在加排他锁之前调用的一个接口内,对于表加了共享锁。 那么此时两个事务的逻辑就变成了: 事务1,analyze先加共享锁,然后加更新锁,最后加排他锁,且加共享锁和拍他锁之间,需要数据采样,计算统计信息等,比较耗时。 事务2,包级复制自更新先加共享锁,然后加排他锁。 由此,问题已经明确,即当事务1拿到共享锁但没拿到排他锁时,事务2开始执行,拿到共享锁。 此时,事务1持有表级共享锁,和更新锁,想要加排他锁,但被事务2的共享锁阻塞。 事务2持有表级共享锁,想要加排他锁时被事务1的共享锁和更新锁阻塞。 即,事务1等待事务2,事务2等待事务1,形成死锁,报错杀死其中一个,继续进行操作。

总结

至此,耗时一下午的事情终于找到问题原因,死锁的确是发生在两个事务之间,但发生在同一个对象上,而不是开始时认为的多个对象。也就是说,除了上面说的多个对象加锁顺序不一致导致的环形等待死锁之外,单个对象上,也可能由于锁优先级和互斥原因,形成环形等待死锁。 以此铭记,希望吃一堑而长一智。

ps:今天是九一八,一个耻辱的日子,其实每到这样的日子总是有些迷茫,不知道自己该以怎样的态度去面对,是怒不可遏,拔刀相向,立刻杀向xxx?还是该沉痛缅怀,垂头痛苦流涕?抑或是充耳不闻,当作没发生?在简书上看到某位作者(这里没有征得作者同意,不敢随便写下别人姓名,甚至于笔名也不敢,若作者看到,期望留下名字,或是觉得放在这里不妥,请与我联系,立刻删除。)的一段话,觉得挺有道理,记录下来,与君共勉。

首先得敢正视,然后必须直面,不护短,不避丑,不掩伤,方能有自省,有自律,有奋起,国民的致富实在重要,国民的精神最是重要。

Table of Contents