一起数据库中过期用户数据堆积问题的排查过程

【文章摘要

对于使用数据库来存放大量用户的软件来说,过期数据的清理机制需要慎重设计。如果设计不当,则会导致数据的误删除或清理不完全。

本文对某数据清理模块因参数配置不当而导致的过期用户数据堆积问题进行了详细的分析,为相关软件问题的分析及解决提供了有益的参考。

一、问题描述

在某软件系统中,为了让不同种类的用户享受对应的服务,引入了一个信箱服务等级的概念,即不同服务等级的用户具有不同的权限。“一分钱,一分货”,对于运营商来说,高服务等级的用户收取高的资费,提供高质量的服务。

为了维护不同用户的信息,在数据库中建立了用户数据表,表中包含了用户号码(如手机号)、状态(如正常使用、停用、欠费等)、服务等级(称作cos值)、用户属性(A或B类用户)等字段。

近期,该软件系统的某商用局点的支持人员反馈回一个问题:数据库中过期用户数据堆积,很多本该被删除掉的数据依然存在。

二、问题原因初步分析

在该软件系统中,有一个过期数据清理模块专门用于清理过期用户数据。既然数据库中出现了大量未被删除的过期用户数据,那么一定是这个模块出了问题。

我们让现场的支持人员将使用的数据库打包返回,并在开发小组的自测数据库中将数据恢复了。我们查看了用户数据表,发现的确有大量过期用户数据还保存在数据库中的。那么,这些本该删除的数据有什么特点呢?

我们对部分过期用户数据进行了观察,发现它们具有以下两个方面的特点:

第一,某个cos值对应的过期用户数据特别多,占到了未被清理的数据量的80%以上。

第二,未被删除的过期用户数据的用户属性大多为B类。

三、问题定位

基于以上分析,我们参照代码和数据库脚本来查找问题原因。

首先,为什么某个cos值对应的过期用户数据特别多呢?难道是这类数据很特别,程序不会对其执行删除操作吗?

我们详细追踪了程序执行流程,发现在数据库脚本中,有一个参数值用于控制是否将过期用户数据删除以及过期多少天的数据要删除。而这个参数的值是在一个cos参数表中定义的。cos参数表的定义如下:

控制过期用户数据删除的cos参数的名字“cosname”为“DelOverdueData”,“cosid”对应的是用户数据表中的服务等级,“cosvalue”表示删除数据的时间阈值。

我们在数据库中执行SQL语句“select cosid, cosvalue from tb_cosparamterwhere cosname = ‘DelOverdueData’”,结果如下:

cosid              cosvalue

1                     0

2                     30

3                     30

4                     40

5                     50

可以看到,服务等级为1的用户数据对应的时间阈值为0,表示不删除。而我们之前查看数据库,确实是cos值1对应的过期用户数据特别多。看来,就是因为这个cos值配得不对,导致了该服务等级对应的过期用户数据无法删除掉。

我们执行SQL语句“update tb_cosparamter set cosvalue= 30 where cosname = ‘DelOverdueData’ and cosid = 1”将cosid为1时对应的cosvalue值修改为30,重新启动清理模块之后,发现确有大量过期数据被删除掉了,但仍有少量用户属性为B的过期数据还存在,什么原因呢?

我们继续追踪数据库脚本,发现有一个参数值用于控制要删除哪类用户数据,这个参数也是在cos参数表tb_cosparamter中定义的。cos参数的名字“cosname”为“DelUserType”,“cosid”对应的是用户数据表中的服务等级,“cosvalue”为1表示只删除A类用户,为0表示A或B类用户都要删除。

我们在数据库中执行SQL语句“select cosid, cosvalue from tb_cosparamterwhere cosname = ‘DelUserType’”,结果如下:

cosid             cosvalue

1                    1

2                    1

3                    1

4                    1

5                    1

可以看到,各个服务等级对应的cos值均为1,表示只删除A类用户。这与我们观察到的情况是一致的。看来,就是因为这个cos值配得不对,导致了用户属性为B的过期数据无法删除掉。

我们执行SQL语句“update tb_cosparamter set cosvalue= 0 where cosname = ‘DelUserType’”将cosname为“DelUserType”对应的cosvalue值修改为0,重新启动清理模块之后,发现用户属性为B的过期数据被删除掉了,数据库中再也没有多余的过期数据了。

四、总结

在过期用户数据堆积问题的排查过程中,我们首先通过对问题数据进行分析来初步查找问题原因,之后通过追踪程序流程来定位问题。

通过本次问题排查,我们总结出的经验有以下几个:

第一,遇到程序问题,我们不要惊慌,可以先从表面上观察问题的现象并推测问题原因,然后再根据之前的分析深入研究程序流程,找到问题关键所在。

第二,对于数据库中的重要数据,要有人员定期进行维护,并作相应的记录。这样才能够避免出现某些参数值不一致的情况。

第三,修改数据库中的相关字段值时,一定要谨慎。在修改之前,尽量将重要表中的数据备份,避免对数据库造成破坏而无法恢复。

不管是程序bug也好,数据库问题也罢,我们的目标都是要尽力将它们解决掉。在解决问题的过程中,我们要采用灵活的处理方法,并沿着发现的蛛丝马迹追查下去。如此这般,不管是什么样的bug都是可以被消灭的。

--------------------------

本人微信公众号:zhouzxi,请扫描以下二维码:

时间: 2024-10-27 14:17:54

一起数据库中过期用户数据堆积问题的排查过程的相关文章

深入理解 WordPress 数据库中的用户数据 wp_user

WordPress 使用 wp_users 数据表存储用户的主要数据,该数据表结构类似于wp_posts 和 wp_comments 数据表,存储的是需要经常访问的用户数据,该数据表的结构以及该数据表与其他数据表的关系如下: WordPress 用户数据表关系(点击查看大图) 同时,WordPress 把一些附加用户数据保存在了其他数据表中,包含附加用户数据的有以下两个数据表: 附加用户属性数据保存在 wp_usermeta 数据表中. 在评论中,未登录用户的数据保存在wp_comments数据

查看MYSQL数据库中所有用户及拥有权限

查看MYSQL数据库中所有用户 mysql> SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query FROM mysql.user; 查看数据库中具体某个用户的权限mysql> show grants for 'cactiuser'@'%';

清空SQL Server数据库中所有表数据的方法

其实删除数据库中数据的方法并不复杂,为什么我还要多此一举呢,一是我这里介绍的是删除数据库的所有数据,因为数据之间可能形成相互约束关系,删除操作可能陷入死循环,二是这里使用了微软未正式公开的sp_MSForEachTable存储过程. 也许很多读者朋友都经历过这样的事情:要在开发数据库基础上清理一个空库,但由于对数据库结构缺乏整体了解,在删除一个表的记录时,删除不了,因为可能有外键约束,一个常见的数据库结构是一个主表,一个子表,这种情况下一般都得先删除子表记录,再删除主表记录. 说道删除数据记录,

统计电视机顶盒中无效用户数据,并以压缩格式输出

前面我们学习了如何使用MapReduce计数器,那么我们通过下面这个项目巩固我们所学 1.介绍 本项目我们使用电视机顶盒数据,统计出无效用户数据记录,并解析出有效的用户数据以压缩格式输出 2.数据集 数据来源于“hadoop小文件合并”处理后的结果 3.分析 基于需求,我们通过以下几步完成: 1.首先使用Jsoup,解析出html格式的机顶盒数据 2.编写Mapper类,自定义计数器统计无效的机顶盒数据,并将有效的机顶盒数据以压缩格式输出 4.实现 1.首先定义一个ParseTVData类,解析

MYSQL 查看数据库中所有用户及拥有权限

查看MYSQL数据库中所有用户 mysql> SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query FROM mysql.user;+---------------------------------------+| query                                 |+---------------------------------------+| User: 'cactiuser'@

数据库中批量导入数据,有两列的值需要从其他表中查出来,我现在没有思路,求解惑

我现在批量往数据库里导正式数据(sql insert),但是数据中有三列分别是岗位,办事处,大区,给的数据中只给了岗位的值,办事处的值可以通过岗位值在岗位表查到,大区的值可以通过办事处的值在办事处表里查到.现在我已经把其他数据都导进去了,只剩办事处和大区没有值,我该如何批量更新这两列的值啊 导入的数据的表: 岗位表: 办事处表: 本人sql不是很好,希望sql大神能给出来解惑一下,拜谢~ 数据库中批量导入数据,有两列的值需要从其他表中查出来,我现在没有思路,求解惑 >> mysql 这个答案描

如何从Zabbix数据库中获取监控数据

做过Zabbix的同学都知道,Zabbix通过专用的Agent或者SNMP收集相关的监控数据,然后存储到数据库里面实时在前台展示.Zabbix监控数据主要分为以下两类: 历史数据:history相关表,从history_uint表里面可以查询到设备监控项目的最大,最小和平均值,即存储监控数据的原始数据. 趋势数据:trends相关表,趋势数据是经过Zabbix计算的数据,数据是从history_uint里面汇总的,从trends_uint可以查看到监控数据每小时最大,最小和平均值流量. Zabb

JavaWeb-SpringSecurity在数据库中查询用户

系列博文 JavaWeb-SpringSecurity初认识 传送门 在MySQL数据库中创建springsecurity数据库 (id.username.password都是根据User.java映射过来的) 在application.properties中编写配置文件 #datasource spring.datasource.url=jdbc:mysql:///springsecurity?serverTimezone=UTC&characterEncoding=utf-8 spring.

SQL Server数据库中导入导出数据及结构时主外键关系的处理

2015-01-26 软件开发中,经常涉及到不同数据库(包括不同产品的不同版本)之间的数据结构与数据的导入导出.处理过程中会遇到很多问题,尤为突出重要的一个问题就是主从表之间,从表有外检约束,从而导致部分数据无法导入. 情景一.同一数据库产品,相同版本 此种情况下源数据库与目标数据库的数据结构与数据的导入导出非常简单. 方法1:备份源数据库,恢复到目标数据库即完成. 方法2:使用SQL Sever数据库自带的[复制数据库]功能或者[导入数据]功能按照向导操作即可. 情景二.同一数据库产品,不同版