当前位置:首页 > 知识 > 用户数据库 正文

用户数据库

时间:2026-10-17 05:06:42 来源:力不从心网

凌晨三点,用户运维群里跳出一条告警:用户数据库主库连接数飙到98%。数据我爬起来连上VPN,用户看到慢查询日志里躺着一句再熟悉不过的数据SQL——SELECT * FROM users WHERE phone = '138****1234'。没有索引。用户就这么一条查询,数据把连接池拖垮了。用户

这就是数据用户数据库的日常。它不像推荐系统那样光鲜,用户也不像日志平台那样能容忍丢几条数据。数据用户表里每一行都对应一个活生生的用户人,手机号、数据密码哈希、用户注册时间、数据最后登录IP,用户这些字段拼在一起,就是这家公司最值钱的东西。

表结构不是设计出来的,是改出来的

我见过不少初创项目的用户表,打开一看,users表里塞了六十多个字段。用户名、邮箱、手机号、微信openid、支付宝uid、头像URL、个性签名、会员等级、积分余额、邀请码、设备号、推送token……全挤在一张表里。问就是“当时赶工期,加字段方便”。

这种表在早期确实跑得动。几千个用户,随便查。等到几十万用户的时候,问题就来了:每次ALTER TABLE加字段,锁表几分钟,业务直接报警。更麻烦的是,很多字段根本不会被同时读取——登录验证只需要手机号和密码哈希,个人主页只需要昵称和头像。把冷热数据混在一起,缓存命中率上不去,磁盘IO倒是先扛不住了。

后来我们做了一次拆分,把users拆成users_auth、users_profile、users_ext三张表。认证表只放登录凭证,走Redis缓存;资料表放展示信息,读多写少;扩展表放第三方绑定和业务属性,按需加载。拆分那天,主库QPS直接掉了四成。

索引不是越多越好,但少了真要命

回到开头那个凌晨。phone字段没索引,是因为当初建表的人觉得“手机号查询不频繁”。可实际上,登录、找回密码、风控校验,全走手机号。一个字段的索引缺失,能在半年后变成P0故障。

但反过来,我接手过一个库,users表上挂了十几个单列索引。写入性能惨不忍睹,每插入一条记录,B+树要更新十几棵。更离谱的是,有些索引从来没用过,EXPLAIN一看,possible_keys列了一堆,key永远是那个主键。

我的习惯是:每上线一个新查询,先看EXPLAIN,再决定加不加索引。组合索引的字段顺序按区分度排,区分度高的放前面。比如(status, created_at)就比(created_at, status)更实用,因为状态值少,先过滤状态能快速缩小范围。

密码哈希这件事,别自己发明

见过用MD5存密码的,也见过用SHA1加固定盐的。最离谱的一个项目,密码哈希算法是md5(md5(password) + salt),salt还是硬编码在代码里的。问为什么这么设计,答曰“网上搜的”。

密码存储只有两个选择:bcrypt或者argon2。bcrypt够用,成本因子设12以上。argon2更现代,但库的成熟度参差不齐。别用SHA家族,GPU爆破太快了。别自己写盐值生成逻辑,password_hash()和password_verify()已经处理好了。

还有,密码重置token别存明文。生成一个随机串,存哈希值到数据库,设置15分钟过期。用户点击链接时,哈希比对。这样即使数据库泄露,攻击者也没法直接重置密码。

备份恢复演练,比备份本身重要

我们每天凌晨全量备份,binlog实时同步到从库。看起来万无一失。直到有一次,一个开发在测试环境执行了DELETE FROM users WHERE id > 0,没加LIMIT,也没开事务。三秒钟,测试库空了。

恢复过程花了四十分钟。问题不在备份文件,在于我们从来没演练过恢复流程。不知道备份文件解压后有多大,不知道xtrabackup的--prepare要跑多久,不知道从库提升为主库需要改哪些配置。那四十分钟里,业务是停摆的。

现在每季度做一次恢复演练。随机选一个从库,用备份重建,记录每一步耗时。把恢复时间写进SLA文档。这事没人催,但真出事的时候,能救命。

用户数据库没什么高深的技术,无非是表结构合理、索引恰当、密码安全、备份可靠。但就是这些基础的事,很多团队做不好。因为用户表太核心了,动它需要勇气,也需要对业务足够熟悉。每次变更前,先问自己一句:如果这一步操作锁表十分钟,业务能扛住吗?

上一篇:黑帽特征
下一篇:win10漏洞扫描工具
推荐内容