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 生成目录树及显示文件大小的代码
Jul 23 Python
Python CSV模块使用实例
Apr 09 Python
pycharm远程linux开发和调试代码的方法
Jul 17 Python
python使用tcp实现局域网内文件传输
Mar 20 Python
python实现顺序表的简单代码
Sep 28 Python
python实现字符串加密成纯数字
Mar 19 Python
简单了解django缓存方式及配置
Jul 19 Python
python 串口读取+存储+输出处理实例
Dec 26 Python
python爬虫搭配起Bilibili唧唧的流程分析
Dec 01 Python
python 办公自动化——基于pyqt5和openpyxl统计符合要求的名单
May 25 Python
Django集成富文本编辑器summernote的实现步骤
May 31 Python
Python爬虫实战之爬取京东商品数据并实实现数据可视化
Jun 07 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页面防重复提交方法总结
2013/11/25 PHP
分享php邮件管理器源码
2016/01/06 PHP
php微信公众号开发之现金红包
2018/04/16 PHP
广泛收集的jQuery拖放插件集合
2012/04/09 Javascript
在JavaScript里嵌入大量字符串常量的实现方法
2013/07/07 Javascript
javascript代码运行不出来执行错误的可能情况整理
2013/10/18 Javascript
js document.write()使用介绍
2014/02/21 Javascript
JavaScript定义变量和变量优先级问题探讨
2014/10/11 Javascript
浅谈JavaScript事件的属性列表
2015/03/01 Javascript
JavaScript中神奇的call()方法
2015/03/12 Javascript
Nodejs学习笔记之测试驱动
2015/04/16 NodeJs
jQuery实现返回顶部效果的方法
2015/05/29 Javascript
JS组件Bootstrap Table表格多行拖拽效果实现代码
2015/12/08 Javascript
完美实现js焦点轮播效果(一)
2017/03/07 Javascript
JS运动特效之任意值添加运动的方法分析
2018/01/24 Javascript
新版vue-cli模板下本地开发环境使用node服务器跨域的方法
2018/04/03 Javascript
VUE 配置vue-devtools调试工具及安装方法
2018/09/30 Javascript
JavaScript基于面向对象实现的无缝滚动轮播示例
2020/01/17 Javascript
JavaScript async/await原理及实例解析
2020/12/02 Javascript
[02:42]岂曰无衣,与子同袍!DOTA2致敬每一位守护人
2020/02/17 DOTA
Python实现删除时保留特定文件夹和文件的示例
2018/04/27 Python
Python实现根据日期获取当天凌晨时间戳的方法示例
2019/04/09 Python
python itchat实现调用微信接口的第三方模块方法
2019/06/11 Python
实现Python与STM32通信方式
2019/12/18 Python
Python装饰器的应用场景代码总结
2020/04/10 Python
解决jupyter运行pyqt代码内核重启的问题
2020/04/16 Python
pandas将list数据拆分成行或列的实现
2020/12/13 Python
网易微博Web App用HTML5开发的过程介绍
2012/06/13 HTML / CSS
美国一家全面的在线零售鞋类公司:SHOEBACCA
2017/01/06 全球购物
Sunglasses Shop瑞典:欧洲领先的太阳镜网上商店
2018/04/22 全球购物
湖南卫视在线视频媒体平台:芒果TV
2019/10/30 全球购物
sort命令的作用和用法
2013/08/25 面试题
简历中自我评价范文3则
2013/12/14 职场文书
教师政风行风评议心得体会
2014/10/21 职场文书
2015小学教育教学工作总结
2015/07/21 职场文书
Springboot中如何自动转JSON输出
2022/06/16 Java/Android