Latest Notes

把日常问题写成可复用的答案。

这里收集技术实践、排错记录、阅读札记和一些生活观察。每一篇都尽量留下清晰的上下文、判断和解决路径。

Today 持续记录,慢慢变好

技术笔记、项目复盘、阅读摘录和问题清单。

开发 10 阅读

Python 环境变量设为 false 仍启用:布尔开关的定位与入口校验

适用场景与现象 一个批处理服务用 EXPORT_ENABLED 控制是否生成导出文件。发布配置里已经写了 false,应用重启后却仍进入导出分支。开发环境不设置该变量时,功能又能正常关闭。 下面用这个场景复现问题。它适用于直接读取环境变量的 Python 程序;如果项目使用配置框架,应先查明框架自己的布尔解析规则,避免

阅读全文
数据库 31 阅读

SQLite 更新主表后明细消失:INSERT OR REPLACE 级联删除的复现与修复

接口返回成功,主表记录也还在,但关联明细突然清空。遇到这种现象,先找到实际执行的 SQL:如果所谓“更新”用了 INSERT OR REPLACE,就要沿着删除路径排查。 本文用一个订单与明细模型复现问题,再把写入改成有明确冲突目标的 UPSERT。实验只使用内存数据库,不连接生产服务。 适用场景与现象 适用于 SQL

阅读全文
网络 81 阅读

POST 接口重定向后请求体丢失:301、302 与 307、308 的定位与修复

适用场景:地址跳转成功,业务请求却变了 接口从 /orders 迁移到 /orders/,或者网关增加域名规范化规则后,调用方开始收到 405、参数缺失,甚至收到 200 的 HTML 页面。调用日志只保留最终响应,看起来像后端突然不认识请求体。 这类问题先查重定向链:客户端发出的第一跳是 POST,不代表最终到达业务

阅读全文
开发 105 阅读

Python JSON 配置被静默覆盖:重复键的复现、定位与入口校验

配置导入接口返回成功,回读结果却与提交内容不一致。先检查客户端发出的原始 JSON:同一个对象里可能出现了两次 quota,而解析器只留下了后一个值。等数据变成字典,再严格的字段校验也找不回被覆盖的那一项。 本文以“批量任务额度配置”为例,把排查推进到解析入口,并提供可以独立运行的实现与回归测试。示例使用 Python

阅读全文
数据库 126 阅读

SQLite 设置超时仍立即报锁错误:WAL 旧快照升级失败的复现与修复

接口先查询计数器,再更新它。连接已经设置 timeout=5,更新却几乎立即返回 database is locked。把超时调到 30 秒仍然失败,而同一条 SQL 在新连接上可以成功。此时要检查失败连接是否持有旧的读快照。 本文针对 Python 3.12+ 标准库 sqlite3、本机文件数据库、WAL 模式和独

阅读全文
开发 157 阅读

Python 3.13、3.14、3.15 有什么区别:新功能、示例与升级检查

服务还在使用 Python 3.13,开发机已经安装 3.14,3.15 又发布了。真正需要判断的是:哪些功能能解决项目里的问题,哪些行为变化会让原来的代码失败,以及如何验证升级没有改变业务结果。 本文以 2026 年 10 月 17 日为时间点,比较三个版本的主要变化。Python 3.13 于 2024 年 10

阅读全文
数据库 147 阅读

SQLite 已声明外键却写入孤儿数据:连接初始化与存量校验实践

订单明细表已经写了 REFERENCES orders(id),导入程序却能插入不存在的订单号。更容易误判的情况是:初始化脚本设置过 PRAGMA foreign_keys = ON,接口仍然产生孤儿明细。 这时先确认写入连接的状态。SQLite 的外键执行开关属于连接;迁移连接开启,不代表接口、后台任务和临时导入脚本

阅读全文
开发 159 阅读

Python 请求参数串数据:可变默认值与浅拷贝的定位和修复

一个报表接口连续执行两次:第一次查询订单,第二次查询库存。库存请求却带上了订单请求追加的字段。重启进程后暂时恢复,压测时又复现。数据库查询本身没有问题,污染发生在构造查询参数之前。 这类故障不一定需要并发:同一进程中两个顺序调用就能触发。本文用纯 Python 标准库复现并修复,适用于长期运行的 Web 服务、任务 W

阅读全文
数据库 173 阅读

PostgreSQL 已有唯一约束却出现重复默认配置:NULL 语义的定位与修复

适用场景与现象 配置表按租户和作用域保存覆盖项:scope_id 有值表示某个具体作用域,为 NULL 表示租户默认配置。业务要求每个租户只能有一条默认配置,每个具体作用域也只能有一条。 表上已经有 UNIQUE (tenant_id, scope_id),压测后却出现两条默认配置。读取接口用 LIMIT 1 暂时掩盖

阅读全文