1. 背景

  1. 今天在测试接口的时候,出现如下问题:
An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

查看error.log日志,出现如下问题:

Lock wait timeout exceeded; try restarting transaction 

在这里插入图片描述

我的代码

class RestPassword(BaseView):

    @transaction.atomic
    def post(self, request):
        tid = transaction.savepoint()
        r = Result()
        try:
            phone = request.data["phone"]
            new_pwd = request.data['newPwd']
            s = SysUser.objects.filter(phone=phone).first()
            s.pwd = new_pwd
            s.save()
            del_token(phone)
            transaction.savepoint_commit(tid)
        except Exception as e:
            r.error(e)
            transaction.savepoint_rollback(tid)
        return self.s_result(r)

2.事故原因

  经查资料后,我发现是因为一些不可控的因素导致mysql事务还未来得及提交,应用就挂了或者其他情况,接着mysql就会出现事务死锁的状态。比如我用上述的代码测此接口,突然网络发生了异常, 还未执行到 transaction.savepoint_commit(tid)这一行, 然后我把应用给停止了,就是那么碰巧,Mysql那边就还没来得及处理该事务,该事务就一直处于获取到锁的状态,锁得不到释放,死锁就产生了。

3. 解决方法

  mysql数据库有一个记录事务获取锁的表,如果发生上述报错产生死锁,那么可以在 information_schema数据库中可以找到痕迹,使用如下sql找到死锁进程,把它们给kill掉即可。

select * from innodb_trx;

查看字段try_mysql_thread_id, 得到进程号码后,使用Kill命令清除掉即可。

kill pid

在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐