用生成列加唯一索引实现软删除下的唯一约束
软删除是业务表的常见设计:加一个 deleted_at 或 is_deleted 字段标记删除,查询时过滤。真删除会绕过这个设计,所以大部分团队都会遇到同一个问题——原本在 email、username、order_no 这类字段上的唯一索引,在软删除之后不再"正确":删除一条记录后再次注册同一个邮箱会撞唯一键,报 Duplicate entry 'a@b.
软删除是业务表的常见设计:加一个 deleted_at 或 is_deleted 字段标记删除,查询时过滤。真删除会绕过这个设计,所以大部分团队都会遇到同一个问题——原本在 email、username、order_no 这类字段上的唯一索引,在软删除之后不再"正确":删除一条记录后再次注册同一个邮箱会撞唯一键,报 Duplicate entry 'a@b.
用 array_walk 配合递归去"顺手"修改嵌套数组,是 PHP 里一个特别容易踩雷的写法。表面上看,回调函数里写了 $value = ...,跑完 print_r 却毫无变化;或者小心翼翼加上 &$value,结果顶层改了、深层没改;再或者想用 array_walk_recursive 一把梭,却发现它拿不到父级键名,也没法直接替换整个子树。这
这道题在面试里出现的频率不低,但绝大多数候选人的回答停留在「脑裂就是两个 master,会丢数据」这个层面,再往下问「丢多少、什么时候丢、窗口多长、怎么算」就答不上来了。实际上 Redis 本身并不具备自动的脑裂防护(Sentinel 的 quorum 只能降低概率,不能消除),数据丢失窗口是有明确数学边界、可以被量化和判定的。这篇文章把窗口的构成拆开算清楚
线上经常遇到这样的场景:监控面板显示 Pod 内存 2.3GiB,而 requests 只给了 512Mi,limits 是 1Gi,于是怀疑监控出错或容器逃逸;另一种情况是扩容时 kubectl top 的值远低于 requests,HPA 一直不缩容,节点资源被白白占着。这两个数据来自完全不同的链路——kubectl top 读的是 metrics-se
商品详情页要同时拿到价格、库存、促销、评价四份数据,四个下游接口串行调用 800ms 起步,改成并行之后 P99 掉到 220ms。但并行带来的新问题是:只要有一个接口卡住,整页就跟着卡住。给每个 future 单独 orTimeout 只能解决单点超时,它抛出的 TimeoutException 会让 allOf 立刻异常结束,其余还在跑的请求白白浪费,而
写 Rust 的时候,只要函数签名里出现 & 而返回值又是引用,编译器就很可能甩出一串 error[E0106]: missing lifetime specifier。新手常见的反应是随手加 'a,加完发现 borrow checker 又在调用点报错,于是继续加,最后把一个本来十行的函数写成生命周期标注的涂鸦墙。 真正需要理解的是:省略规则(lifeti
线上排查一个 Go 服务的错误日志时,发现所有经过 defer 包装的错误,errors.Is 全都返回 false,日志里的 %+v 也看不到原始堆栈。代码长这样: func LoadConfig(path string) (cfg *Config, err error) { defer func() { if err != nil { err = fmt
在 Nginx 里做反向代理,最容易踩的坑之一,就是 location 前缀和 proxy_pass 尾部斜杠的搭配。表现往往是:本地用 curl 直连后端 200,经过 Nginx 就变成 404;或者用 /api/health 探活一直 404,但日志里看不出任何"配置错误"——因为 Nginx 认为一切正常,它只是把你请求的 URI 按规则改写后转发出
用 paramiko 对几十上百台机器批量跑命令,最容易踩的两个坑是:远端命令卡住导致线程永久阻塞,以及stderr 没读干净导致 exit_status 拿到 None。前者会让整个批量任务的时间不可控,后者会让你明明看到失败却拿不到错误原因。paramiko 本身没有内置的命令级超时,exec_command 的 timeout 参数只作用于 chann