开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, Oceanbase, Sql Server等有问题,有需求都可以加群群内有各大数据库行业大咖,可以解决你的问题。加群请联系 liuaustin3 ,(共2310人左右 1 + 2 + 3 + 4 +5+6) 新人分配到6群,准备建立7 群。*(1 2 3 4 5 均没有空位了,请不要在问了谢谢)
最近群里一个知名的软件服务商的领导,说他的系统服务的客户很多还在用MySQL5.6,5.7 然后群里说还有用5.5的了。哎MySQL 的老版本的用户不少,大部分还在MySQL 5.7上转悠。说是升级的热情不高,当然这与ORACLE 对MySQL的8.0版本的“不负责”,有关,也与不少用户目前使用MySQL5.7并没有遇到问题有关。
但这里提示能升级MySQL的同学还是进来升级,MySQL到8.018版本以上(不包括8.029)。因为最近我们出现了一个严重的MySQL的故障,版本是MySQL 5.7.28,Official 版本。
系统已经持续运行了有5-6年了,没有问题,但突然一天CPU升高,接近100%,并且持续的高,我们抓取了慢查询日志,发现其中有一个SQL 与这个问题有关,随机我们进行了测试,执行计划完全走了索引,一个这样简单的SQL 竟然要90-120秒,这让我们不可思议。随即我们将SQL 在从库进行了测试,发现从库运行这个SQL的速度异常的快只要0.006秒。
select
distinct RES.*,
AR.ID_ as VAR_ID_,
AR.NAME_ as VAR_NE_,
AR._TYPE_ as V_TYPE_,
AR._ as VAR_REV_,
AR.C_INST_ID_ as VR_PC_ID_,
AR.CUT_ID_ as VR_EXECUID_,
AR.K_ID_ as R_SK_ID_,
AR.EA_ID_ as VAR_BAY_ID_,
AR.BLE_ as VAR_DLE_,
AR.T_ as VR_XT_,
AR.T2_ as VR_TET2_,
AR.T_UPDD_TI_ as VAR_ST_TED_ME_,
AR.G_ as V_LG_
from
tcn.AC_HI_TST RE
left outer join tcn.NST AR ON RE.PNST_ID_ = AR.EXON_ID_
and VAR.TK_ID_ is null
WHERE
RES.ID_ = '173878637'
order by
VAR.LAST_UED_TIME_ asc
LIMIT
20000 OFFSET 0;
这里最大的问题是他有主从库,主库是运行的是不OK的,但是从库运行是非常快的,同样的数据,同样的SQL,进行explain的时候也是同样的执行计划。
到底是为什么,通过show engine innodb status,和各种系统表也分析了当前写库是否有大事务,或者表被霸占,或大事务等情况,统统的没有,就是慢,慢,慢 fack!!!
冷静下来分析
1 主库和从库数据一致,语句一致,执行计划一致 2 在主库实际运行语句最快1分30秒 ,在从库运行0.005秒。
此时在想,如果是MySQL8 就好了,我们可以使用explain format = 多种显示的方式,并且还能trace 具体的执行计划,而不是在这里看着简单的执行计划,并看着业务部门在问到底怎么回事。在问题分析这块,MYSQL5.7就是一个傻子。
然后只能从语句上下手,尝试,语句中有两个点 1 ORDER BY 2 limit N,M
因为MySQL有一个致命的问题这在8.0后也有类似的问题,但在高版本将这个问题的参数默认给关闭了,ORDER BY LIMIT 执行效率的问题。
问题主要表现在 where condition order by A limit N 这样的语句,由于MYSQL5.7默认是打开 prefer_ordering_index 也就是在操作的时候,由于limit N 的值比较小,导致查询分析器去走ORDER BY 字段上的索引,而放弃更适合的索引。
摆在我面前的有几个方案
1 去设置optimizer_switch='prefer_ordering_index=OFF' 2 尝试添加一个比现在索引权重更大的索引 (需要看条件,不是每次都能行) 3 强制语句使用 hint
由于这个.28的版本比较老,记得应该是.33后的MySQL才可以添加 prefer_ordering_index参数所以第一个选择的方案不可以。
那么就需要尝试剩下的方案,我先尝试第三个方案,的确在强制hint index后,语句执行的速度┗|`O′|┛ 嗷,的一下子就快了,0.006秒,看来的确是和语句执行没有走正确的索引有关,配合监控中的执行语句的时候iops就超高,估计是是3千500万的表在进行全表的扫描。尝试了多次,只要语句执行不HINT,IOPS 就超高。
但是让开发去给你改语句,虽然开发说可以,但觉得对不起开发,这数据库的稳定性也忒差了,我尝试第二个方式,正好这个查询中在left join 中带有一个其他的条件,那么我就舱室重建索引,将原来的单字段的索引,改成复合的字段,这样从查询计划的实现上也是有利于数据查询的,在添加这个复合的索引后,再次尝试语句,速度也是┗|`O′|┛ 嗷的一下子蹦到 0.005秒。
先对这些方案,还是通过添加索引来进行问题的解决,让几方更能接受,后面打算对mysql的小版本进行升级,当然如果能推动往 MYSQL 8.018的版本上进行升级最好是 8.025就更好了,那么后续的一些DDL等操作也会更顺手,同时对于GROUP BY的语句执行的方式有了更大的优化,在低版本MYSQL无法运行的复杂的SQL,在8.025以上的版本运行也会更加的顺畅。
官方对此知识的文档
https://dev.mysql.com/doc/refman/5.7/en/limit-optimization.html
置顶文章:
PostgreSQL 稳定性平台 PG中文社区大会--杭州来去匆匆
往期热门文章:
MySQL 的SQL引擎很差吗?由一个同学提出问题引出的实验
临时工访谈:从国产数据库 到 普罗大众的产品 !与在美国创业软件公司老板对话
感谢 老虎刘 刘老师 对 5月20日 SQL 问题纠正贴 ---PostgreSQL 同一种SQL为什么这样写会提升45%性能
PostgreSQL 同一种SQL为什么这样写会提升45%性能 --程序员和DBA思维方式不同决定
PostgreSQL 熊灿灿一句话够学半个月 之 KILL -9
临时工访谈:庙小妖风大-PolarDB 组团镇妖 之 他们是第一 (阿里云组团PK笔者实录)
临时工访谈:金牌 “女” 销售从ORACLE 转到另类国产数据库 到底 为什么?
临时工访谈:无名氏意外到访-- 也祝你好运(管理者PUA DBA现场直播)