客服后台按手机号后四位搜索,输入 8866 返回 0 条,数据库里其实有 12 个匹配的号码,改成全号精确查也查不到,因为查询条件直接拿明文去比密文。乍看像缓存或者权限的锅,追下去往往不是。
SELECT id, phone_last4 FROM users WHERE phone_last4 = '8866'; SELECT count(*) FROM users WHERE phone_hmac = '9f2c';
追下去是这么回事:加密列上的等值和模糊查询都需要额外结构,密文本身不保留明文顺序和片段。后台还在按明文拼 like,SQL 永远匹配不上。团队没有为检索单独设计索引列。
「加密字段检索」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。
先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。
具体做法是,增加手机号后四位的单独索引列 明文存储 只用于检索;全号查询走 HMAC 精确匹配;后台列表展示仍然解密 但查询不碰密文列;用尾号 8866 再搜一次核对条数。
验收就看一点,尾号搜索返回 12 条 和数据库里的实际数量一致。
