加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.0354zz.com/)- 科技、容器安全、数据加密、云日志、云数据迁移!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

站长必避的3个MySQL设计陷阱:半年一崩

发布时间:2026-11-02 14:36:08 所属栏目:MySql教程 来源:DaWei
导读:  去年十二月,慢查询报警挂满钉钉群,我正啃冷掉的葱油饼,屏幕右下角弹出 17 条慢日志——全是同一个表,SELECT 加 LIMIT 0,20,跑了俩小时。不是卡,是直接 hang 在 InnoDB 的 row_search_for_nth_row 上,线程状态卡在 “Se

  去年十二月,慢查询报警挂满钉钉群,我正啃冷掉的葱油饼,屏幕右下角弹出 17 条慢日志——全是同一个表,SELECT 加 LIMIT 0,20,跑了俩小时。不是卡,是直接 hang 在 InnoDB 的 row_search_for_nth_row 上,线程状态卡在 “Sending data”。我原以为又是开发又在查表不加索引,结果一扒 schema:主键是 BIGINT 自增,但业务上根本不用 ID 做任何关联,所有 JOIN、WHERE、ORDER BY 全靠一个叫 “biz_code” 的 VARCHAR(32) 字段,而它没索引,连个普通索引都没有。


  风扇一直在转,声音比平时高半档,我切到终端敲了句 SHOW CREATE TABLE,手抖按错成 SHOW CREATE DATABASE,回车之后才反应过来——不是数据库错了,是脑子先崩了。旁边运维老张路过,看了眼我屏幕,问了句“好了没”,我说“没,这字段建表时忘加索引了”,他哦一声就走了,背影特别笃定,好像早知道这天会来。其实我信了半年——他们说“反正流量不大”,“后面再加”,“上线先跑通”。结果半年整,卡在圣诞节前夜。不是崩溃,是瘫痪。MySQL 进程活着,连接数满,CPU 持续 97%,SELECT 就像往干涸河床里泼水,一滴都渗不下去。


  第二个坑是时间戳字段用的 DATETIME 而不是 TIMESTAMP,而且没设 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP。本来没啥,直到开发写了个“更新最后操作时间”的逻辑,却忘了 WHERE 条件漏了主键——一行 UPDATE 把全表三百万行 datetime 刷成了 '0000-00-00 00:00:00'。这事不报错,SQL 执行成功,日志里写着 “3,247,891 rows affected”。我是在第二天凌晨看 binlog 重放时才发现的:所有最近数据“最后更新时间”倒退回了五年前。领导微信问我“为什么后台显示的‘最新文章’全是 2019 年的”,我没回,先去把备份拉出来——结果发现备份策略是每周日凌晨做一次 mysqldump,中间七天零增量。我原以为主从延迟能救一手,结果从库也被这条语句同步了。窗外天黑了,手机亮着,领导头像还挂着“对方正在输入…”。


文章配图,仅供参考

  第三个最绝:所有表 ENGINE=InnoDB,但建表时显式加了 ROW_FORMAT=COMPACT,然后所有人当它是个摆设。直到某次批量导入后,某个表的 .ibd 文件大小暴涨三倍,IO 飙高,运维老张说“磁盘 iowait 跑到 85%”,我第一反应是硬件问题。查了一圈发现——这个 COMPACT 格式在默认页大小 16KB 下,对含大量 VARCHAR(512) + TEXT 的列组合,实际存储碎片率超过 60%,更骚的是 MySQL 不会自动回收那些碎片空洞,OPTIMIZE TABLE 又被禁用(“怕锁表影响线上”)。我们用的是阿里云 RDS,官方文档清清楚楚写着:“ROW_FORMAT=COMPACT 已被弃用,建议使用 DYNAMIC”。没人读。没人管。没人觉得一个“格式声明”能决定你能不能撑过春节流量峰。我翻 git log 查建表语句,提交人是刚毕业三个月的实习生,备注写着“抄的模板”。那模板是谁写的?没人记得了。


  中午那顿饭我点了三次外卖,第一次凉了,第二次送到时我在追 binlog,第三次打开盒子,米饭结块,青菜蔫成灰绿色。隔壁组开发小陈跑过来问:“你们库是不是又拖慢我们服务了?”我盯着他工牌上的入职日期——今年七月,比我晚五个月。我突然有点烦,不是烦他,是烦自己:明明八月份那轮 review 我就提过 biz_code 缺索引,但会议纪要里写的是“排期评估中”,技术债台账编号是 DB-2023-041,现在快成文物了。技术债不是欠钱,是欠认知;等你还的时候,本金早利滚利成灾变。


  说到备份……其实我上周偷偷改过一次策略,在从库上开了一条 crontab 每两小时 dump 一次关键表,不走主库,也不进正式流程。运维老张撞见,叼着烟说“你这算违规操作啊”,我说“那您告我呗”,他笑了一声,顺手把我脚边喝空的红牛罐踢进了废纸篓。有些事不能上台面,但得有人踩一脚底线。这不是高可用,是垂死挣扎。可垂死挣扎,总比等崩了再跪着求恢复强。


  现在我在重写那个建表模板。把 biz_code 设成唯一索引加前缀索引;datetime 字段补默认和更新触发;ROW_FORMAT 强制改成 DYNAMIC;还加了一行注释:“如果敢删这行注释,罚请全组奶茶”。我知道没用。三年后新来的实习生照样抄,照样删。站长不是输在不懂 SQL,是输在“这次先凑合”。半年一崩,听着夸张,其实是优胜劣汰——扛不住半年的站,迟早被自动筛选掉。我们不是在修数据库,是在给业务方争取不被用户遗忘的时间窗口。窗口关得太快,不是 MySQL 的问题,是决策流速压过了数据流速。我手边还开着一个未关闭的 tab:阿里云控制台里那个红色的“释放实例”按钮,悬停三秒后会弹出二次确认。我还没点。但鼠标已经在这儿停了挺久。

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!