技术博客

把报表导出从分页查询中拆出来

报表能正常显示一页筛选结果,导出相同范围却明显更慢。流程已经使用流式工作簿写入器,批次大小和写入器配置自然成为排查方向。

沿数据提供层继续检查,发现每个输出批次都会重新进入列表分页流程:计算总数、执行分页查询、转换这一批数据,再追加到工作簿。文件在逐批写入,数据库执行却不断重新开始。

本次本地修复让导出拥有独立的执行生命周期。下文依据本地测试和受控只读比对说明已完成的部分;修复包尚未部署,生产 HTTP 提速也尚未验收。

先统计语句执行次数

列表页需要一段结果,有时还需要总数来计算页码。全量下载需要读完本次选中的结果,再生成完整文件。

旧实现把每个写入批次绑定到新的分页操作,反复支付计数和分页 …

新增逐次事件时,不要伪造历史明细

每日计数可以回答发生了多少次请求,却无法说明每次请求检测到的名称、精确时间和读取方式。当页面已经显示非零的 AI 请求总数,却没有任何逐次访问可列出时,这个差异就会直接暴露出来。

系统需要为新流量保存更丰富的记录,同时保留旧总数原本的含义。如果把一个历史计数拆成几条看似合理的明细,界面会更整齐,证据却会变弱。因此,这次演进保留旧聚合作为聚合,只为实际观测到的新请求写入事件,并向读者明确标出两者边界。

信息在聚合时已经丢失

旧模型保存文章 slug、语言、规范化 AI 家族、UTC 日期和请求次数。这些字段足以计算每日总量,却没有单次请求的客户端名称、时间、检测来源,也没有记录客户端读取 …

把批量删除收口到持久化与事务边界

用户在列表中选中多条记录后点击删除,请求返回 HTTP 500。数据库最早错误来自一条拼接明细文本的分组查询,这条查询原本服务于页面展示。删除操作因此继承了一个自身并不需要的读取依赖。

问题还跨越了多个层次:浏览器逐条发起删除请求,控制层没有稳定保留服务结果,服务层先加载扩展展示对象,再定位需要删除的持久化记录。后续步骤一旦失败,页面很难确认整批选择究竟已提交、部分执行,还是完整回滚。

修复为破坏性操作建立了一个清晰边界:服务端一次接收整批目标,读取精确的持久化模型,先校验全部记录,再在同一事务内按依赖顺序删除,最后把真实结果返回页面。

沿最早错误定位,再继续检查调用链

数据库日志记录了聚合投 …

用明确日界线修正“今日”指标

一个运营页面把两项顶部异常数标成“今日”。只读查询按本地当天筛选后,得到的记录数明显更少。排查期间业务持续流转,数量自然会变化,但每轮比较都稳定出现一批属于昨日的记录。

源码中的日期范围解释了差异:下界是昨日零点,上界是今日最后一秒。查询返回的异常记录都真实存在,区间却覆盖了两个自然日。页面标签与实现分别给出了不同的指标定义。

修复为“今日”建立唯一且明确的契约。两项顶部查询都基于同一个请求时刻和指定业务时区生成边界,再用相同条件下的完整明细及业务主键去重数进行验证。

修改查询前先证明日期区间

排查对齐了四类证据:

  • 页面上的指标名称和刷新行为;
  • 服务传入两项顶部查询的参数;
  • 线上数据库语句缓 …

用真实流转证据计算业务流程状态

一个运营看板开始把订单提前推进到后续阶段:收货刚完成,页面就显示卸货或检验;订单已经发运,报表却仍把它标成较早的核对阶段。真实业务交易还在继续,状态报表描述的操作边界已经偏离现场。

故障同时涉及读写两端。报表接受了流转表中的全部记录,其中包括没有开始时间的行,以及为未来阶段提前生成的占位记录。另一个业务入口在当前阶段结束时立即创建下一阶段里程碑。两类信号进入同一条排序链后,“取最新一条”无法稳定说明哪项工作已经开始。

最终修复把当前状态改成一项可复核的推导结果:先分类流转证据,再统一历史编码,只在事件缺失时使用有限的业务补偿,同时把里程碑写入移到真实转换位置。所有报表视图都改为消费同一个解析结 …

Oracle 架构同步脚本如何防误库并支持重复执行

用于升级演练的数据库从一份有效快照复制而来。复制完成后,来源端又增加了结构和字典变化。测试应用开始验收前,目标库需要补齐这些变化,才能得到可比较的基线。

目标库已有部分升级结果,还保留了一项比来源定义更宽、经过验证的兼容改进。同步范围也明确排除了业务记录。若直接顺序执行一组无条件 ALTER、CREATE 和 INSERT,脚本可能在中途遇到重复对象,下一次执行仍会失败;操作人员一旦选错连接,同一组语句还可能落到错误数据库。

最终脚本把同步描述为期望状态:先核对目标身份,再于写入前分类全部差异,只补缺失项,执行后逐项验收,最后完整运行第二次验证零变化路径。

先明确同步边界

来源对比只做读取,并 …