用 JSON_TABLE 把单据明细 JSON 数组拆行并关联主表统计金额
很多业务系统在设计单据表时,把明细行整体存进一个 JSON 列(比如 order_header.detail_json),主表只留单号、客户、状态等字段。这样做写入简单、结构灵活,但一到对账、报表、按商品汇总金额的环节就卡住:MySQL 不能直接对 JSON 数组里的每个元素做聚合。开发常见的土办法是把数据全捞到应用层用 Java/Python 循环展开,再
FWDD.NET · 技术文档站
聚焦后端工程实践:语言教程、功能实现、面试题与运维脚本。每篇都从真实踩坑场景出发,给出可直接复用的代码与取舍依据。
很多业务系统在设计单据表时,把明细行整体存进一个 JSON 列(比如 order_header.detail_json),主表只留单号、客户、状态等字段。这样做写入简单、结构灵活,但一到对账、报表、按商品汇总金额的环节就卡住:MySQL 不能直接对 JSON 数组里的每个元素做聚合。开发常见的土办法是把数据全捞到应用层用 Java/Python 循环展开,再
把一个 @dataclass 实例丢进 set 或当作 dict 的 key,很快会遇到两类问题:一是 TypeError: unhashable type,二是「明明字段值不同,却被集合判成同一条」或者反过来「以为是同一条,却出现两条」。前者来自 dataclass 默认把 __hash__ 置为 None,后者来自 eq 与 frozen 两个开关对 _
线上排查一个用户操作日志丢失的问题时,链路信息(traceId、userId)在 Controller 里明明已经写进了 InheritableThreadLocal,可一进业务代码里通过 @Async 或手动提交的线程池任务,日志里的 traceId 就全变成 null。很多人第一反应是"继承的 ThreadLocal 没生效",于是继续在工具类上加装饰、
签名 URL(signed URL)在对象存储、下载站、付费资源分发里非常常见:服务端用密钥对「路径 + 过期时间」做 HMAC,把签名拼进查询串;客户端拿着这条 URL 在有效期内可以直接下载,过期后返回 403。真正难的不是签名算法本身,而是过期策略的可测试性——如果代码里直接写 time.Now(),你就要么 sleep 到过期(测试变慢且不稳定),要
rsync 增量备份本身很可靠,但一旦被 cron 或 systemd timer 调度起来,就会遇到两个非常现实的问题:第一,上一次备份还没跑完(源端文件多、网络慢、磁盘抖动),下一次调度又启动了,两个 rsync 进程同时写同一个目标目录,轻则重复传输浪费带宽,重则 rsync: mkstemp "/backup/.../.file.XXXXXX" fa
容器突然消失,docker ps -a 里状态显示 Exited (137),运维第一反应往往是「被 OOM 杀了」。但这个判断在多数情况下是错的:退出码 137 只说明进程收到了 SIGKILL(信号 9,128+9=137),而 SIGKILL 的来源至少有四种——cgroup 内存超限被内核 OOM killer 选中、docker stop 超时后
业务里最常见的翻页 SQL 大概是 SELECT * FROM t ORDER BY id LIMIT 20 OFFSET 500000。前几页很快,翻到几万页之后响应时间从十几毫秒涨到几秒,CPU 和 IO 一起飙升,慢查询日志里全是它。这不是 MySQL 的 bug,而是 OFFSET 语义决定的成本:数据库必须先定位并跳过前 N 行,再取 M 行。本文
把 Option<T> 转成 Result<T, E> 时,ok_or 和 ok_or_else 是编译器提示里出现频率最高的一对方法。多数人凭直觉选:错误值简单就用 ok_or,需要格式化就用 ok_or_else。这个直觉方向没错,但理由常常说不清,于是代码里出现两种极端:一种是无脑全用 ok_or,在热路径上白白构造了一个立刻被
在 Go 服务里做批量处理时,最常见的形态是:一个任务列表,每个元素触发一次下游调用(HTTP、RPC、数据库查询),希望并发跑得快,但又不能把下游打爆,于是需要限流;同时任何单个元素失败不应该中断整批,而是跑完后汇总所有失败项。手写 sync.WaitGroup + chan error + 信号量 channel 可以做到,但很容易踩到三个坑:错误 ch