python编程项目中线上问题排查与解决


Posted in Python onNovember 01, 2021

文 | ?O光

来源:Python 技术「ID: pythonall」

最近开发中遇到个小问题,因为业务上的设计存在问题,导致数据库表总是被锁,而且是不定期的锁定,导致服务器运行异常,最后经过排查原因是多线程同时更新同一表中同一条记录导致问题。今天就来跟大家说说该如何避免这种问题。

问题描述

最近因为公司业务需要,产品设计了一套业务系统,据说会有很多内部和外部人员使用,拿到系统说明我们研发部门拼命加班赶时间,经历了两个月的后终于把系统上线运行。

刚开始用的人少,并没有出现什么问题,感觉系统还是很稳定,随着后来用的人越来越多,系统就开始出现一些莫名其妙的问题,其中就有某些业务信息在更新的时候总是报错,查日志就发现是表记录被锁定导致更新失败。

找到错误问题后我们就开始一遍遍的翻日志,各种分析查找到底是什么原因导致了表记录被锁。最后发现这个表的状态字段,存在多个接口方法同时更新的情况,而且经常是同时操作的。也就是数据库中存在多个会话同时操作同一表中同一行记录,从而导致表记录被锁。

问题分析

那定位到问题,要如何解决呢?这里我们先了解两个名词:

悲观锁(Pessimistic Lock):简单解释就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在修改数据的时候都会上锁,这样别人想修改这个数据就会等待一直到它能拿到锁。

乐观锁(Optimistic Lock):这个正好相反,就是很乐观,每次去修改数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。乐观锁适用于读多写少的应用场景,这样可以提高吞吐量。

通过这两种方式就能解决问题,不过选哪种比较好,我们来简单分析下:

  • 悲观锁 通过 “select …… for update” 实现,就是在更新表前先对这条记录进行上锁,然后下面再执行更新语句。不过这种方式有些太重,毕竟加锁还是需要很大时间成本的,不符合业务的需要,直接pass掉。
  • 乐观锁 相对就要轻量很多,它的主要实现就是通过在表中多增加一个记录版本的字段,比如 version 。然后每次查询记录要更新时,where 后面都要加上 version=? ,这样当你查询拿到 version 后,如果有其他会话更新了这个字段,那这个 version 就会和你现在拿的不一样,从而会使你这次的更新失效,需要重新获取最新 version 后再次执行 update 语句。

问题解决

好了,经过以上分析,已经有了比较清晰的解决思路,剩下就是码代码了:

/**
     * 乐观锁更新
     * @param id
     * @return
     */
    public boolean update(int id){
        int cnt = 0;
        while (cnt == 0) {
            USER user = query("SELECT * FROM table_user WHERE id = #{id}", id);
            cnt = update("UPDATE table_user SET version=version + 1, status = 2 WHERE id=#{id} AND version=#{version}", id, user.version());
            if(cnt > 0){
               // 返回更新成功
                return true;
            }
        }
        return false;
    }

总结

这里只是基于 Mysql 自身特性解决这个问题,当然还有很多其他的方式可以解决,例如通过 Redis 或者 MQ 消息队列等,如果大家感兴趣我们可以以后再介绍。

更多关于python线上问题排查与解决的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
详细探究Python中的字典容器
Apr 14 Python
Python实现定时任务
Feb 08 Python
python urllib urlopen()对象方法/代理的补充说明
Jun 29 Python
在Python程序员面试中被问的最多的10道题
Dec 05 Python
mac PyCharm添加Python解释器及添加package路径的方法
Oct 29 Python
Python将一个Excel拆分为多个Excel
Nov 07 Python
python基于C/S模式实现聊天室功能
Jan 09 Python
Python 限制线程的最大数量的方法(Semaphore)
Feb 22 Python
如何安装并使用conda指令管理python环境
Jul 10 Python
python模块如何查看
Jun 16 Python
Pycharm中使用git进行合作开发的教程详解
Nov 17 Python
如何用Python搭建gRPC服务
Jun 30 Python
python实现层次聚类的方法
Python list列表删除元素的4种方法
Nov 01 #Python
Python面向对象编程之类的概念
Nov 01 #Python
python代码实现扫码关注公众号登录的实战
python编程实现清理微信重复缓存文件
Nov 01 #Python
python调用ffmpeg命令行工具便捷操作视频示例实现过程
Nov 01 #Python
Python字典的基础操作
Nov 01 #Python
You might like
PHP的mysqli_query参数MYSQLI_STORE_RESULT和MYSQLI_USE_RESULT的区别
2014/09/29 PHP
教大家制作简单的php日历
2015/11/17 PHP
php版微信公众平台入门教程之开发者认证的方法
2016/09/26 PHP
js中document.write使用过程中的一点疑问解答
2014/03/20 Javascript
JS中的form.submit()不能提交表单的错误原因
2014/10/08 Javascript
jquery.cookie.js使用指南
2015/01/05 Javascript
jquery图片切换实例分析
2015/04/15 Javascript
javascript实现链接单选效果的方法
2015/05/13 Javascript
jQuery+css实现的切换图片功能代码
2016/01/27 Javascript
jquery拖拽排序简单实现方法(效果增强版)
2016/02/16 Javascript
JavaScript判断页面加载完之后再执行预定函数的技巧
2016/05/17 Javascript
微信小程序商城项目之商品属性分类(4)
2017/04/17 Javascript
js轮播图无缝滚动效果
2017/06/17 Javascript
微信小程序实现底部导航
2018/11/05 Javascript
解析原来浏览器原生支持JS Base64编码解码
2019/08/12 Javascript
js prototype和__proto__的关系是什么
2019/08/23 Javascript
vue.js实现左边导航切换右边内容
2019/10/21 Javascript
js获取本日、本周、本月的时间代码
2020/02/01 Javascript
基于ant design日期控件使用_仅月份的操作
2020/10/27 Javascript
Python常用字符串替换函数strip、replace及sub用法示例
2018/05/21 Python
Python多进程入门、分布式进程数据共享实例详解
2019/06/03 Python
python实现高斯(Gauss)迭代法的例子
2019/11/20 Python
Python实现RabbitMQ6种消息模型的示例代码
2020/03/30 Python
使用css3实现的windows8开机加载动画
2014/12/09 HTML / CSS
英国舒适型鞋履品牌:FitFlop
2017/05/17 全球购物
将世界上最美丽的摄影作品转化为艺术作品:Photos.com
2017/11/28 全球购物
吉力贝官方网站:Jelly Belly
2019/03/11 全球购物
毕业生个人的自我评价优秀范文
2013/10/03 职场文书
中专生自我鉴定书范文
2013/12/28 职场文书
春季运动会广播稿大全
2014/02/19 职场文书
追悼会主持词
2014/03/20 职场文书
就业意向书范文
2014/04/01 职场文书
园林技术专业求职信
2014/07/28 职场文书
初中学习计划书范文
2014/09/15 职场文书
redis中lua脚本使用教程
2021/11/01 Redis
Nginx动静分离配置实现与说明
2022/04/07 Servers