news 2026/6/26 2:48:52

读写分离导致批量删除逻辑问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
读写分离导致批量删除逻辑问题

原始代码实现

@Override public void clearExpireOrder(LocalDate expireDate) { log.info("开始清理过期订单, 过期日期: {}", expireDate); int batchSize = 200; long totalDeletedCount = 0; while (true) { List<ExposureOrder> expireOrders = this.list(Wrappers.<ExposureOrder>lambdaQuery() .select(ExposureOrder::getId).le(ExposureOrder::getAdEndDate, expireDate.atStartOfDay()) .last("LIMIT " + batchSize)); if (expireOrders == null || expireOrders.isEmpty()) { break; } List<Long> ids = expireOrders.stream().map(ExposureOrder::getId).collect(Collectors.toList()); int deletedCount = this.removeByIds(ids) ? ids.size() : 0; totalDeletedCount += deletedCount; log.info("本批次删除 {} 条过期订单, 累计删除 {} 条", deletedCount, totalDeletedCount); if (deletedCount < batchSize) { break; } } log.info("过期订单清理完成, 总计删除 {} 条数据, 过期日期: {}", totalDeletedCount, expireDate); }

这是一个清理过期订单的定时任务,传入一个过期时间,每次查询前200个过期订单并根据ID进行删除。然而,在生产环境执行后,发现仍有过期订单存在。查询日志显示:

5月 15, 2026 @ 03:00:01.850 开始清理过期订单, 过期日期: 2026-04-15 5月 15, 2026 @ 03:00:01.850 本批次删除 200 条过期订单, 累计删除 200 条 5月 15, 2026 @ 03:00:01.850 本批次删除 0 条过期订单, 累计删除 200 条 5月 15, 2026 @ 03:00:01.850 过期订单清理完成, 总计删除 200 条数据, 过期日期: 2026-04-15

从功能上看,先查询后删除的方式虽然不是最佳方案,但代码逻辑上确实看不出明显问题。经过反复分析,仍未能找出错误所在。

问题发现

突然注意到数据库连接地址为prod-bd-traffic-mysql-shm-01.rwlb.rds.aliyuncs.com:3306,这看起来像是阿里云的代理链接地址。经检查,我们的数据库配置为一主一从,并启用了数据库代理的读写分离功能。

阿里云RDS的数据库代理地址开启读写分离功能后,会根据执行的SQL自动将请求分发到RDS的主节点或从节点,实现读写分离。回到原始代码,问题出在以下执行流程:

  1. 执行查询操作(路由到从节点)
  2. 执行删除操作(路由到主节点)
  3. 再次执行查询操作(仍然路由到从节点,但此时从节点尚未同步主节点的删除数据)
  4. 第二次查询与第一次查询结果相同
  5. 执行删除操作,受影响行数为0
  6. 认为已没有需要删除的数据,跳出循环

问题解决方案

找到问题根源后,修改代码策略,不再采用先查询后删除的方式,而是直接执行DELETE语句:

@Override public void clearExpireOrder(LocalDate expireDate) { log.info("开始清理过期订单, 过期日期: {}", expireDate); int batchSize = 100; int maxBatch = 1000; int currentBatch = 0; long totalDeletedCount = 0; while (true) { LambdaUpdateWrapper<ExposureOrder> w = Wrappers.<ExposureOrder>lambdaUpdate() .le(ExposureOrder::getAdEndDate, expireDate) .last(" LIMIT " + batchSize); int deletedCount = this.getBaseMapper().delete(w); totalDeletedCount += deletedCount; log.info("本批次删除 {} 条过期订单, 累计删除 {} 条", deletedCount, totalDeletedCount); if (deletedCount == 0) { break; } else if (currentBatch > maxBatch) { log.warn("本次清理超过最大处理批次, 退出清理"); throw new RuntimeException("本次清理超过最大处理批次, 退出清理"); } else { try { Thread.sleep(200); } catch (InterruptedException e) { log.error("线程中断, {}", e.getMessage()); } } currentBatch ++; } log.info("过期订单清理完成, 总计删除 {} 条数据, 过期日期: {}", totalDeletedCount, expireDate); }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 2:47:47

突破窗口限制:用Window Resizer打造完美工作空间

突破窗口限制&#xff1a;用Window Resizer打造完美工作空间 【免费下载链接】WindowResizer 一个可以强制调整应用程序窗口大小的工具 项目地址: https://gitcode.com/gh_mirrors/wi/WindowResizer 你是否遇到过这样的烦恼&#xff1f;某个应用程序的窗口死活无法调整到…

作者头像 李华
网站建设 2026/6/26 2:46:37

反激flyback电路

一、反激的三种模式CCM模式&#xff0c;变压器每个周期的能量没有完全释放完&#xff0c;下一个周期的驱动信号就来了&#xff0c;在此阶段初期&#xff0c;开关管关断时&#xff0c;漏感尖峰迅速冲高&#xff0c;随后被吸收电路&#xff08;如 RCD 吸收回路&#xff09;压制&a…

作者头像 李华
网站建设 2026/6/26 2:43:46

YOLO26涨点改进| TGRS 2026 | 卷积创新改进篇| 引入ARFC自适应感受野卷积,根据不同区域小目标的尺度动态选择合适感受野,助力遥感小目标检测、旋转目标检测、小目标检测,有效涨点

一、本文介绍 🔥本文给大家介绍使用ARFC自适应感受野卷积改进YOLO26网络模型,ARFC 通过 网格级路由器 将局部特征分配给不同的 多感受野专家 MFE,小尺度目标倾向于使用小感受野专家以保留细节、减少背景干扰,较大目标则使用大感受野专家以获取更充分的上下文;同时结合 长…

作者头像 李华
网站建设 2026/6/26 2:43:30

Abode AE安装包

本软件资源仅可用于个人技术研究、学习交流与非盈利性实验场景。严禁将本程序及其衍生内容用于各类商业经营、盈利项目、对公业务等商业行为。若有商业化使用需求&#xff0c;请联系著作权方获取正式授权并采购正版授权版本&#xff0c;严格遵守软件著作权相关法律法规。分享文…

作者头像 李华
网站建设 2026/6/26 2:40:33

3dsmax更换背景的详细操作

第一步&#xff1a;载入图片到环境槽&#xff0c;快捷键8在“公用参数”面板下&#xff0c;看到那块写着 “无” (None) 的灰色长条按钮吗&#xff1f;点击那个“无”字按钮。此时会弹出一个“材质/贴图浏览器”窗口&#xff1a;在左侧的搜索框里输入 “位图” 或者 “Bitmap”…

作者头像 李华
网站建设 2026/6/26 2:37:34

大模型抽取字段总缺漏怎么补全校验

把结论甩出来&#xff1a;大模型做结构化字段抽取漏字段&#xff0c;八成不是模型笨&#xff0c;是你没给它"漏了也得交差"的兜底。补全靠两步——强制 schema 占位&#xff08;缺的字段也得吐出来、标 null&#xff09; 抽完做一遍规则校验回填。下面按我踩过的具体…

作者头像 李华