程序员不要好心办坏事
开发中我们看那些散发着浓烈的badsmell的代码,总有一种要修理它的冲动!这当然是好事,说明我们有能力识别不好的东西以及维持系统健康运行的意愿。但是,但是总是无处不在,我们好心有时候会办出坏事来。下面这个真实的案例就是某同学觉得表的字符集设计得不合理,在一次需求开发中就把他改了,然而不幸的是由此导致了一个不小的线上事故,下面分享给大家1。事故的导火线
你敢想?导致线上事故的是一个简单的DDL语句:
ALTERTABLEtabletCONVERTTOCHARACTERSETutf8mb4;2。事故现场
由于业务系统响应极慢,使用方反馈(早期系统没有完善的告警机制),开发排查日志发现是sql查询速度很慢,然后查询慢日志监控,看到了如下的壮观场景:
慢sql监控信息3。事故原因分析
为什么会有这么多慢查询呢??因为查询语句的关联字段的字符集不同,导致索引失效,sql执行变成了全表扫描,进而导致数据库实例所在机器的CPU长时间100,影响业务访问。4。事故线下重现
我们使用连接查询时,两个表的关联字段都建有索引,但是如果两个表的关联字段的字符集不同,就会导致索引失效,不会走索引。执行下面的建表语句:CREATETABLEt1(
idbigintNOTNULLAUTOINCREMENT,
nameVARCHAR(64)DEFAULT,
codeVARCHAR(16)DEFAULT,
PRIMARYKEY(id),
KEYidxcode(code),
KEYidxname(name)
)ENGINEInnoDBAUTOINCREMENT6DEFAULTCHARSETUTF8;CREATETABLEt2(
idbigintNOTNULLAUTOINCREMENT,
nameVARCHAR(64)DEFAULT,
codeVARCHAR(16)DEFAULT,
PRIMARYKEY(id),
KEYidxcode(code),
KEYidxname(name)
)ENGINEInnoDBAUTOINCREMENT6DEFAULTCHARSETUTF8MB4;
然后插入一些数据:INSERTINTOt1(id,name,code)VALUES(6,aa,);
INSERTINTOt1(id,name,code)VALUES(7,bb,);
INSERTINTOt1(id,name,code)VALUES(8,0,);
INSERTINTOt1(id,name,code)VALUES(9,1,);
INSERTINTOt1(id,name,code)VALUES(10,2,);
INSERTINTOt1(id,name,code)VALUES(11,3,);
INSERTINTOt1(id,name,code)VALUES(12,4,);
INSERTINTOt1(id,name,code)VALUES(13,5,);
INSERTINTOt1(id,name,code)VALUES(14,6,);
INSERTINTOt1(id,name,code)VALUES(15,7,);
INSERTINTOt1(id,name,code)VALUES(16,8,);
INSERTINTOt1(id,name,code)VALUES(17,9,);
INSERTINTOt2(id,name,code)VALUES(6,ff,);
INSERTINTOt2(id,name,code)VALUES(7,hh,);
INSERTINTOt2(id,name,code)VALUES(8,gg,);
线上的sql形式如下:
selectfromt2leftjoint1ont1。codet2。codewheret2。nameff;
我们查看执行计划:
explainextendedselectfromt2leftjoint1ont1。codet2。codewheret2。nameff;
从下图的执行计划可以看到,查询条件t2。nameff使用了索引,而条件t1。codet2。code并没有使用表t1的索引:
sql执行计划
为什么两个字段的字符集不一样就不走索引了呢?这个命令SHOWWARNINGS;会给你详细的说明分析,这个命令和执行计划配合使用,简直不能再香了。你一定要去使用!如下:
执行的warnings信息
message全量内容如下:
select1selecttest。t2。idASid,test。t2。nameASname,test。t2。codeAScode,test。t1。idASid,test。t1。nameASname,test。t1。codeAScodefromtest。t2leftjointest。t1on((convert(test。t1。codeusingutf8mb4)test。t2。code))where(test。t2。nameff)
这时候已经非常清楚了,MySQL在关联字段上进行了convert转化,索引当然就失效喽!5。事故解决
问题的解决也是简单粗暴,DBA直接改回了原来的字符集:
ALTERTABLEttestCONVERTTOCHARACTERSETutf8;6。事故复盘
平时让我们说索引失效的场景你可能会咔咔咔地说出不少,但是实际使用的时候却时常会犯错,实际上还是意识不强烈。不管怎么说,都要认真对待自己写下的每行代码,包括任何要上线的资源,如初始化的数据,脚本等。就拿这次事故来说,开发同学本意是觉得utf8字符集不严谨,应该使用utf8mb4,但实际上表中的code字段存储的只是数字和字母组成的字符串,早期历史原因被设计成utf8也无可厚非了。但是,我们作为后来接手者,任何改动就要小心了,避免跳坑里了。
OK,咱们回聊
科莫多巨蜥的毒液到底有多可怕?2009年,一名31岁的渔民安瓦尔,在印尼科莫多岛上采摘水果,结果不小心从水果树上掉了下来,刚好踩到了一只巨型蜥蜴,蜥蜴瞬间就朝他扑了过去,咬住了他的腿,之后又咬住了他的手臂,身体
武汉未来的房价会涨到100000元平米吗?这个问题的答案是肯定的!以目前的趋势,未来武汉房价必然达到10万的水平,只是时间长短的问题。2010年至2017年,短短七年间,武汉的房价已经翻了3番,目前,武汉部分高端楼盘如洞庭
兰州青白石片区,中央公园怎么样?兰州北拓的黄金区域,目前基础交通还跟不上建设需要,交通滞后可能会成为十四五期间兰州青白石片区发展的的最大障碍!不过就兰州地理位置和城区格局而言,青白石片区是离主城区最近的待开发区域
农民为什么不在国家统计失业范围之内?中国有四个儿子,大儿子叫工人,二儿子叫子弟兵,三儿子叫公务员,四儿子叫农民,所以四儿子就没有纳入统计失业包括养老金范围,因为四儿子有金山银山还有三分地。农民有土地,这是农民可以赖以
农村成立社区是什么意思?很多农村驻有村委会办公室,同时也驻有社区管理委员会办公室,特别是在城市郊区的农村和街道的农村都同时设立了村委会和社区管理委员会,很多人弄不明白是怎么回事。那农村成立社区是什么意思呢
农村里的剩男,为何一剩再剩呢?到底是什么原因?男女比例失调。计划生育只要一个孩子时,受封建思想影响,都拚命要男孩,等他们长大了,很难找到媳妇。一,农村姑娘远嫁,二,女孩见少,三,彩礼高,四,剩男挣钱少。我就一大龄剩男!个人亲身
抖音付费直播试水,看直播要给钱了?我们应该如何思考?使劲收,最好是家人们看的话,一分钟100块钱。毕竟粉丝听话的很。毕竟人设都设计好了打PK,卖货摆错价格,怒亏2个亿回馈粉丝。没事就怼工厂,怼员工反正就是赔钱回馈粉丝。赔完还得补交税
马上就要退休了,退休工资才3650元太少了,怎么办?3600不少了。我企业工龄32年,退休时退休金只有2200,涨了这么多年还不到3000。知足常乐吧!如果身体不好,这些钱也够生活了,如果身体还可以,就找一些力所能及的工作,打打工补
南宁五象新区未来的发展潜力很大吗?五象新区无法成为国家级新区!!!目前看来,五象新区的潜力也就这样了。我们对比一下贵阳的贵安新区,贵安新区的面积是1700平方公里,由贵阳市的郊区和安顺市合并得来。是全国第8个国家级
如果把三峡大坝加高10米,截留更多的洪水,可行吗?我国的三峡大坝,作为当今世界上最大的水利枢纽工程,位于湖北省宜昌市上游,距下游葛洲坝水电站38公里,三峡大坝全长2309米高185米,呈梯形形状,集发电旅游航运调控洪水于一身。三峡
大家有经历过亲人去世吗?是怎样走出痛苦和想念的?2018年9月1日下午3点8分,我的妻子在医院里停止了呼吸。她的眼睛没有闭上,我流着泪,帮她合上了双眼。我永远失去了我最亲近的爱人,孩子永远的失去了妈妈。一位好妻子,好女儿,好姑妈