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

目录
  • 问题描述
  • 问题分析
  • 问题解决
  • 总结

文 | 極光

来源: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线上问题排查与解决的资料请关注我们其它相关文章!

(0)

相关推荐

  • python线程中的同步问题及解决方法

    多线程开发可能遇到的问题 假设两个线程t1和t2都要对num=0进行增1运算,t1和t2都各对num修改1000000次,num的最终的结果应该为2000000.但是由于是多线程访问,有可能出现下面情况: from threading import Thread import time num = 0 def test1(): global num for i in range(1000000): num += 1 print("--test1--num=%d" % num) def

  • Python生成器常见问题及解决方案

    在Python中,生成器和函数很像,都是在运行的过程中才会去确定各种变量的值,所以在很多情况下,会导致各种各样的问题. def generator_test1(): # 0...9 generator x = (i for i in range(10)) # 5..9 generator x_filter = filter(lambda y: y >= 5, x) # first use the x L = list(x) print("L, x", L) # then use

  • 使用Python脚本实现批量网站存活检测遇到问题及解决方法

    做渗透测试的时候,有个比较大的项目,里面有几百个网站,这样你必须首先确定哪些网站是正常,哪些网站是不正常的.所以自己就编了一个小脚本,为以后方便使用. 具体实现的代码如下: #!/usr/bin/python # -*- coding: UTF-8 -*- ''' @Author:joy_nick @博客:http://byd.dropsec.xyz/ ''' import requests import sys f = open('url.txt', 'r') url = f.readline

  • Python中遇到的小问题及解决方法汇总

    本文会把学习过程中遇到的一些小问题和解决办法放在这里,以便于大家能够更好地学习python. 一.Python的异常处理 因为想到自己不断尝试写小程序的话会用到抛出异常信息来判断哪里出现了问题: usage: raise [Exception [, args [, trackback]]] 上面是Python的raise的用法,下面是自己用这个方法实现异常的抛出方法: def check_args(args): if not args.host: msg = 'Args missing! One

  • 新手常见Python错误及异常解决处理方案

    写Python代码的小伙伴不可避免地会遇到代码执行错误和异常,这次就来详细且不失通俗地总结一下python中的错误和异常. 先抛出两个问题: 什么是Python错误和异常? 如何处理Python错误和异常? 1.语法错误可能是初学者最常遇到的,如下面熟悉的画面: SyntaxError: invalid syntax语法错误又称解析错误,又有老哥会问什么是解析错误?简单来说是基本语法结构写错了,如:多任务写成一行.for循环没加':'等.如下: 多任务写成一行 for循环没加':' 上面示例可以

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

    目录 问题描述 问题分析 问题解决 总结 文 | 極光 来源:Python 技术「ID: pythonall」 最近开发中遇到个小问题,因为业务上的设计存在问题,导致数据库表总是被锁,而且是不定期的锁定,导致服务器运行异常,最后经过排查原因是多线程同时更新同一表中同一条记录导致问题.今天就来跟大家说说该如何避免这种问题. 问题描述 最近因为公司业务需要,产品设计了一套业务系统,据说会有很多内部和外部人员使用,拿到系统说明我们研发部门拼命加班赶时间,经历了两个月的后终于把系统上线运行. 刚开始用的

  • Python编程之黑板上排列组合,你舍得解开吗

    考虑这样一个问题,给定一个矩阵(多维数组,numpy.ndarray()),如何shuffle这个矩阵(也就是对其行进行全排列),如何随机地选择其中的k行,这叫组合,实现一种某一维度空间的切片.例如五列中选三列(全部三列的排列数),便从原有的五维空间中降维到三维空间,因为是全部的排列数,故不会漏掉任何一种可能性. 涉及的函数主要有: np.random.permutation() itertools.combinations() itertools.permutations() # 1. 对0-

  • python socket通信编程实现文件上传代码实例

    这篇文章主要介绍了python socket通信编程实现文件上传代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 写一个file_receive.py和一个file_send.py程序,由file_send.py上传一个文件,file_receive.py接收上传的文件,写到指定的包内 #file_receive.py import socket,subprocess,os BASE_DIR = os.path.dirname(os.pa

  • Python编程不要再使用print调试代码了

    目录 1. 快速安装 2. 简单案例 3. 详细使用 3.1 重定向到日志文件 3.2 跟踪非局部变量值 3.3 设置跟踪函数的深度 3.4 设置调试日志的前缀 3.5 设置最大的输出长度 3.6 支持多线程调试模式 3.7 自定义对象的格式输出 给大家推荐本我自己写的电子书<PyCharm中文指南>,把各种 PyCharm 的高效的使用技巧用GIF动态图的形式展示出来.有兴趣的可以看它的在线文档: http://pycharm.iswbm.com 对于每个程序开发者来说,调试几乎是必备技能.

  • Python编程之基于概率论的分类方法:朴素贝叶斯

    概率论啊概率论,差不多忘完了. 基于概率论的分类方法:朴素贝叶斯 1. 概述 贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类.本章首先介绍贝叶斯分类算法的基础--贝叶斯定理.最后,我们通过实例来讨论贝叶斯分类的中最简单的一种: 朴素贝叶斯分类. 2. 贝叶斯理论 & 条件概率 2.1 贝叶斯理论 我们现在有一个数据集,它由两类数据组成,数据分布如下图所示: 我们现在用 p1(x,y) 表示数据点 (x,y) 属于类别 1(图中用圆点表示的类别)的概率,用 p2(

  • Python编程使用NLTK进行自然语言处理详解

    自然语言处理是计算机科学领域与人工智能领域中的一个重要方向.自然语言工具箱(NLTK,NaturalLanguageToolkit)是一个基于Python语言的类库,它也是当前最为流行的自然语言编程与开发工具.在进行自然语言处理研究和应用时,恰当利用NLTK中提供的函数可以大幅度地提高效率.本文就将通过一些实例来向读者介绍NLTK的使用. NLTK NaturalLanguageToolkit,自然语言处理工具包,在NLP领域中,最常使用的一个Python库. NLTK是一个开源的项目,包含:P

  • python编程培训 python培训靠谱吗

    我们在论坛和贴吧上看到无论是老的程序员和新手都想更快的入门和精通python编程,但是市面上众多的书籍让大家无从下手,很多书籍和视频都声称能够快速学习,时间有限,大家哪有精力一个个尝试呢,我们的小编和技术人员根据大家这方面的困惑,全面分析一下关于python编程培训等方面的问题,希望我们的分析能让你的python学习之路有一个方向. 如果你是新手还没有入门,那么找一本不错的书籍是你学习python的比较好的途径之一,我们先给大家分享基本有价值的python编程书籍: python编程学习电子书

  • 新手入门Python编程的8个实用建议

    前言 我们在用Python进行机器学习建模项目的时候,每个人都会有自己的一套项目文件管理的习惯,我自己也有一套方法,是自己曾经踩过的坑踩过的雷总结出来的,现在在这里分享一下给大家,因为很多伙伴是接触Python编程入门不久,也希望大家少走弯路,多少有些地方可以给大家借鉴. 目录先放出来 项目文件事先做好归档 永远不要手动修改源数据并且做好备份 做好路径的正确配置 代码必要的地方做好备注与说明 加速你的Python循环代码 可视化你的循环代码进度 使用高效的异常捕获工具 要多考虑代码健壮性 1.

  • 如何教少儿学习Python编程

    如何给少儿讲编程? 1.首先给少儿讲编程一定要简单,通俗易懂. 因为少儿接触的事务比较少,你要用形象的少儿可以接受的方式让他们理解. 2.讲编程的速度一定要慢. 因为少儿的接受能力相对较弱一些,所以要适当调慢步骤. 3.讲编程一定要少儿亲手实践. 因为编程本来就是抽象的事物,如果不进行练习的话,少儿不能很好理解抽象的事物. 4.一定要多复习. 少儿的自觉力差些,课上一定要先复习再讲新的知识. 知识点扩展: 我们需要明确,给孩子上编程课的目的是什么 我想,对于中小学年龄段的孩子,编程课的主要目的应

  • Python编程应用设计原则详解

    目录 1.单一职责原则 SRP 2.开闭原则 OCP 3.里氏替换原则 (LSP) 4.接口隔离原则 (ISP) 5.依赖反转原则 (DIP) 最后的话 写出能用的代码很简单,写出好用的代码很难. 好用的代码,也都会遵循一此原则,这就是设计原则,它们分别是: 单一职责原则 (SRP) 开闭原则 (OCP) 里氏替换原则 (LSP) 接口隔离原则 (ISP) 依赖倒置原则 (DIP) 提取这五种原则的首字母缩写词,就是 SOLID 原则.下面分别进行介绍,并展示如何在 Python 中应用. 1.

随机推荐