数据库字段未更新
程序员文章站
2024-03-21 08:07:16
...
场景
- 内推过来的用户,账号状态为未**,只有当用户通过手机走注册流程,才**账号(正常状态)
发现问题原因
- 新需求:
需要对刚注册用用户实时打标(涉及业务知识可忽略),之前发MQ逻辑是在完成注册时发,这里的注册包括账号是未**状态的注册。
考虑到这样做不合理,所以将发MQ消息放在用户注册时才处理。
- 修改后测试
由于注册需要发送验证码后才能调用手机注册接口,想到麻烦,将代码推送到测试环境验证,结果第一个手机从未**到**状态正常;但当第二个未**手机注册时,发现数据库还是未**状态
又测试同一个手机号也是一样的问题
结果在线上测试问题一致,未**到**时,账号状态未更新
问题分析
- ORM层使用mybatis-plus(3.0.2)
- 最先想到可能是plus版本问题,升级到最新版本(3.3.1) 问题依然存在
// 最初通过如下修改状态
User user = new User();
user.setId(123);
user.setStatus(0);
user.updateById();
/**
* 因为通过设置状态为0,plus不会封装条件(status = 0)
* 之后通过本地测试,未**到**流程,测试OK(但这里是单元测试,只运行一次)。测试环境第一次运行都是OK的,至于原因可能是mybatis-plus对查询做了缓存(仅猜测,没深究)
* 又尝试过使用对象的 user.saveOrUpdate userManger.insertOrUpdate 等原始方法,就连手写SQL,都是同样问题
**/
user.saveOrUpdate();
userManger.insertOrUpdate();
userManger.updateInactivated(Integer id, Map<String, String> options);
- 尝试加sql打印日志 参见配置
- 增加配置后,依然没有输出SQL(如果在这一层深究,可以提前一半时间解决),然后怀疑是数据库原因…
- 因为刚好这段时间DBA升级MySQL版本到 5.7.29-32-log
- 账号状态字段配置 非空,默认值0
- 猜测可能是由于默认值引起的
默认值0,刚好是我要设置的值
那就在代码层面临时使用新值替换账号状态为正常情况,之前0表示账号正常,现在将4也作为账号正常测试
到测试环境后,第一次也是正常的,后续次数测试问题依旧存在
- 取消数据库账号状态默认值,设置可为空
问题依旧
- 后来想到注册之后立马登录,会构造登录会话,写入最后登录IP,时间等
// 公共登录方法很少修改,没有想到是这个方法的问题
// 公共登录方法有这么一个逻辑
User user = userManager.getById(id);
user.setLastLoginIp("127.255.255.255");
...
user.updateById();
- 打印日志 – 设置状态后,在从库取出账号状态,一路都是0(正常)
- 在修改最后登录IP时(userManager.getById(id)),打印日志状态不是0(问题根源在此)
- 将这里getById修改为 User user = new User(); user.setId(123); 即可
问题解决
- 底层通过get、select等方法,走从库查询,insert、update、delete方法走主库修改,主从同步存在一定延迟
- 这里涉及到主从配置 参照mybatis-plus多数据源配置
- 如果能将SQL输出的问题进行到底,问题解决节省一大半时间
- 在家测试,连VPN巨慢,后天在公司分析下没有输出SQL的原因
推荐阅读
-
数据库字段未更新
-
解决distinct中使用多个字段的方法 博客分类: 数据库 distinctoracle
-
MSSQL数据库中Text类型字段在PHP中被截断之解 博客分类: PHP数据库 phpsql
-
SqlServer 获取 当前地址下 所有数据库字段信息 / 快速 批量插入数据库(TVPs)
-
同时修改某一个数据库中所有表的所有字段的编码格式(mysql)
-
会话标识未更新问题
-
Oracle_多条语句的更新操作 博客分类: 7.数据库
-
查询数据库中某个值是否在这个字段中
-
MYSQL的group_concat()函数中实现将多行同一字段数据合并成一个数据 博客分类: 数据库 sqlMySQL
-
数据量大的表的分表方案 以及 跨(同类型的)表查询遇上分组时需要注意的点 博客分类: 数据库 同类型的表跨表查询时间字段分表