记一次MySQL死锁排查过程

背景

大概说一下业务场景,需要定时计算一些数据,从其他系统、接口拉取达到的数据比较多,然后经计算后的值存储在本系统中。拉取的数据量可能有万左右,然后以主键存在的数据是需要更新的。不存在则插入。每次做全量更新/插入。

起因

最开始采用的方法是先查询,数据存在则更新数据,不存在则插入数据。但是数据要求的时效性比较高。于是定时任务在做任务处理的时候频率就比较高了。就出现了单位时间内对数据库的读写高,于是就换了一个方法。用INSERT … ON DUPLICATE KEY UPDATE。

对数据库的读写次数虽然比之前少了,但是又引发了一个新的问题,因为更新、插入的数据量多,所以导致与一条INSERT … ON DUPLICATE KEY UPDATE的执行时间有点长,大概5s,去研究了下。实际上一次批量插入几千条条数据。为了解决这个问题,就分组批量查询,分为了每 50 条数据一组,这样每条sql 执行的时间也就短了。

随之又出现了另外一个问题,随着数据量的增加,一次循环拉取的数据经计算,写入,更新等。时间大于定时任务所处理的时间,这样就导致与上一个定时任务还没处理完的时候,下一个定时任务又进来处理数据了。

于是选择的做法是在每处理一组数据的时候,把 redis 的key 延长一点时间。然后整组数据处理完的时候,再删除 redis 的 值。等下一次定时任务抢到锁了再进来处理。

想到的第二个方案是,直接插入数据库,主键冲突就抛错,根据指定的错来更新值

分享到 评论