最新动态:截至2025年8月,MySQL 8.4版本中FOUND_ROWS()函数已被正式标记为废弃特性,许多开发者迁移数据库时意外触发了3965错误警告,这已成为近期社区讨论热点问题之一。
上周三晚上十点半,我正瘫在沙发上刷短视频,突然企业微信炸出一连串报警——电商平台的订单查询接口集体抽风,虽然系统还在勉强运行,但日志里全是刺眼的警告:
[Warning] [MY-013965] [Server] FOUND_ROWS() is deprecated
and will be removed in a future release. Consider using
COUNT(*) instead. Error: 3965
这个报错最烦人的地方在于:它不会直接让服务挂掉,但会在日志里疯狂刷屏,搞得监控系统天天报警,运维同事差点把我工位给拆了。
简单来说就是你用了MySQL里一个"过气"的功能,FOUND_ROWS()这函数以前常配合SQL_CALC_FOUND_ROWS使用,比如这样的查询:
SELECT SQL_CALC_FOUND_ROWS * FROM orders LIMIT 10; SELECT FOUND_ROWS();
这套组合拳原本是用来获取不考虑LIMIT时的总行数,但MySQL团队现在觉得这玩意儿:
所以从MySQL 8.0开始就贴上了"deprecated"标签,直到最近版本开始频繁警告。
如果半夜被报警吵醒需要快速消停警告,可以临时在my.cnf里加:
[mysqld] sql_mode='-NO_DEPRECATED_FOUND_ROWS'
或者动态执行:
SET GLOBAL sql_mode=CONCAT(@@sql_mode,',NO_DEPRECATED_FOUND_ROWS');
这相当于给MySQL喂了片"别哔哔"药,但注意这只是把警告憋回去,问题还在那没解决呢。
把原来花里胡哨的两条查询改成:
-- 先查总数 SELECT COUNT(*) FROM orders WHERE ...; -- 再查分页数据 SELECT * FROM orders WHERE ... LIMIT 10;
虽然要多发一次查询,但实测在8.0+版本反而更快,特别是配合好索引的情况下。
如果你们已经用上较新版本,可以秀一波操作:
SELECT *, COUNT(*) OVER() AS total_rows FROM orders WHERE ... LIMIT 10;
一条查询直接返回数据+总数,优雅得不像实力派。
用我们订单表(约1200万数据)做了个简单测试:
方案 | 平均耗时 | 峰值内存 |
---|---|---|
原方案(FOUND_ROWS) | 450ms | 2GB |
COUNT(*)方案 | 380ms | 800MB |
窗口函数方案 | 410ms | 750MB |
意外不?老方法居然是最慢的!而且内存占用还高。
我们开发小王在改造时搞出了个神操作:
SELECT COUNT(*) INTO @total FROM orders; SELECT * FROM orders LIMIT 10; -- 然后业务代码里直接用@total
结果在高并发场景下,这个会话变量@total经常串数据,导致分页总数随机漂移,差点被运营同事祭天,正确的做法应该是在事务内完成查询,或者把总数直接返回给客户端。
最后说句掏心窝的:这种不痛不痒的警告最容易被人忽视,但指不定哪天MySQL来个版本升级就直接报错不兼容了,趁现在还有警告提醒,赶紧处理了吧,别等真出事了再加班改。
本文由 少峰 于2025-08-03发表在【云服务器提供商】,文中图片由(少峰)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://vps.7tqx.com/wenda/522305.html
发表评论