乾貨分享:MySQL之化險爲夷的【鑽石】搶購風暴

  搶購鑽石不稀奇,稀奇的是有錢賺不到,事情發生在2015年5月20日,大好的日子天然少不了商家的參與。便可爲您還原現場,解決思路獻給各位,請欣賞Show Time,everybody~mysql

一、優化原由及工做準備

  2014年5月20日下午三點四十接到對方不肯意透漏姓名的「王大錘」領導的電話,對方火急火燎的僅提供了網站訪問慢一條信息,當時博主那個內心一萬隻XX奔騰而過,俗話說的好,酒肉穿腸過,拿人錢財必替人消災。web

  對博主來講網站訪問慢,首先不能亂了陣腳,先想到的就是看web、先看靜態,若是靜態ok就看動態,若是還不ok就看存儲,再不行就看訪問DB時長是否正常。此時緣由就能夠定位了。不會再有其餘緣由了。若是你太菜,那你能夠把個人思路背過,相信對你來講是一個很好的幫助,此時一邊與對方溝通更可能多的得到信息,但是對方一點都不懂,只好無能爲力,與對方協商相關責任制後當即登陸服務器(本人兼職XX鑽世界集團技術顧問一職)。sql

  憑藉我的經驗查看web負載並不高,靜態訪問速度正常,因爲線上活動正在進行,晚一分鐘對商家便是損失,此時沒法進行許多系統的排查,直接則判斷是不是後端DB的問題?隨登陸DB查看負載。發現DB負載不正常,就沒有進行其餘的判斷(什麼IO看一下啊,內存看一下啊,網卡看一下啊,再看公司都倒閉了。),緊急恢復問題就是最大化的恢復問題,找到問題所在即刻解決問題。此時判斷數據庫有慢查詢。數據庫

1 ================2015年5月20日 13:38:08日負載以下:================
2 [lcp@ZCdb01 ~]$ uptime
3 13:50:36 up 122 days, 21:51, 1 user, load average: 6.44, 5.76, 5.38
4 
5 [lcp@ZCdb01 ~]$ uptime
6 13:51:38 up 122 days, 21:22, 1 user, load average: 8.01, 6.30, 5.58

二、判斷問題所在 

 隨登陸數據庫show full processlist;此工具運維人員必備,幹了幾年的運維別說你不會。不會的話看了個人博客也應該會了後端

連抓了兩遍以後發現,這一堆東西不動啊,前面排着的update被鎖定,想寫還寫不進去。select過多,讀也讀不出來。緩存

1 mysql> show processlist;
2 +----+-------------+-----------+------+---------+------+-----------------------------------------------------------------------------+------------------+

三、定位待優化語句

再返回來看後面的查詢語句是經過三個條件進行查詢的。因而定位了待優化的語句也就是下方的select出現次數最多的語句
                         ↑↑↑查詢語句如上↑↑↑

  隨後抓出一條命令explain,屢次確認後加SQL_NO_CACHE不讓其走緩存再反覆確認,最終判斷次語句沒有創建索引或走索引,共查閱7萬3千多條數據耗時驚人。服務器

1 mysql> select SQL_NO_CACHE id from **_**_detail where ader='**_**-jazz_flash' and dateline='**_**' and pos='**_**';

  此時看到可能走的索引和索引都是不存在的。獨立奔跑在七萬多條語句中運維

1 possible_keys:NULL
2 
3         key:NULL
4 
5       rows:71328  #接近全盤掃描

   我記得這臺機器是戴爾服務器2850很老的一臺服務器,但這很明顯不是硬件問題,隨問對方的主管,有沒有人對這臺機器進行優化,一邊電話詢問一邊進行查看,去證明本身的想法,使用show查看錶結構show create table **_**_detai\G,果不其然,除了主鍵索引,一個索引都沒有創建(爲這臺年老失修的服務器感到驕傲,它居然扛了那麼久授小弟一拜)。工具

 

四、解決方案

  扯淡歸扯淡咱們繼續,此時已耗時3分鐘,創建索引的規則相信你們也都清楚,此處不過多解釋,一會看總結。獲得以上結論後,查看哪一字段列的惟一值數量較多。使用select count(distinct XX)from **_**_detai;以上三個語句都使用次等命令查看,最後發現三列的數值爲766/531/154都不高,緣由是有一列是日期,它的惟一值是最少的,第二列看不懂。。優化

  再使用select count(*) from **_**_detail;命令查看一下總數量達到了七萬多條的數量。

  根據以上的狀況,並且查詢語句裏面也很特殊都是等號。這種狀況下創建索引就容易走索引。這種狀況下考慮走聯合索引。根據以上信息及諮詢研發經理其餘語句的狀況下,建立以下索引:

1 mysql> create index d_a_p on **_**_detail(dateline,daer(20),azz(10),pos(20));

  語句的查詢順序是詢問的研發經理,由於聯合索引有前綴生效的特性,因此此時肯定了索引以後並無直接建立,而是與研發經理協商,此時須要殺掉幾個讀的請求。在前面選幾個。show proacesslist;update根據業務需求去考慮。謹慎使用至於殺掉的方法..kill+id相信沒幾個不會的吧。

  索引創建完成再使用explain查看索引是否生效,而後一樣仍是使用select+SQL_NO_CACHE參數不走緩存查詢語句。發現此時僅掃描了12條語句,查詢時間更是少之又少。

  再次使用show proacesslist;查看mysql線程,幾乎看不到了。說明效果很明顯。

  

五、解決效果

  優化以後的負載,已經從以前的6.x、8.x慢慢降低爲2.x,1.72,五分鐘後降到了0.0七、0.21的正常值

 1 [lcp@ZCdb01 ~]$ uptime 
 2  13:59:09 up 120 days,  21:29,  2 users,  load average: 2.40, 4.62, 5.09
 3 [lcp@ZCdb01 ~]$ uptime 
 4  13:59:29 up 120 days,  21:29,  2 users,  load average: 1.72, 4.32, 4.98
 5 [lcp@ZCdb01 ~]$ uptime 
 6  13:59:30 up 120 days,  21:29,  1 users,  load average: 1.66, 4.26, 4.95
 7 [lcp@ZCdb01 ~]$ uptime 
 8  14:05:27 up 120 days,  21:35,  1 users,  load average: 0.07, 1.39, 3.42
 9 [lcp@ZCdb01 ~]$ uptime 
10  14:05:35 up 120 days,  21:36,  1 users,  load average: 0.21, 1.38, 3.40

六、總結

   問題判斷+解決時長10分鐘之內

     優化判斷+後期觀察15分鐘左右

     這次問題解決總用時25分鐘左右

   這次問題因爲對方對mysql數據庫優化不到位,此公司並沒有相關技術人員,平常維護工做沒法正常開展,致使突發情況訪問異常。爲保證之後服務器正常工做,優化完成後在配置文件(my.cnf)下添加以下參數記錄慢查詢語句。

1   long_query_time =2 #<==超過2秒,記錄到LOG裏。
2 
3   log_queries_not_using_indexes #<==沒有走索引的語句,記錄到LOG裏。
4 
5   log-slow-queries = /data/3306/slow.log #<==LOG文件

  可是創建索引的前提是,生產場景,表中數據多的狀況下及高峯期不能創建索引,例如:300萬記錄。因爲這次問題解決中使用的是聯合索引,聯合索引的特性是前綴生效,這也是有別於其餘索引,因此建立時更爲謹慎,須要與開發共同商議建立規則。不然索引無效。

  關於mysql的優化今後次解決問題的過程當中得出如下幾個結論:

  一、緊急狀況抓慢查詢SQL語句:

    登陸數據庫

    show full prcesslist;

  二、未雨綢繆:重要不緊急:分析慢查詢日誌。(生成日誌方法在上述總結中有具體參數)

    分析慢查詢SQL語句,天天定時發郵件給相關工做人員,核心開發、高級運維或DBA

    天天切割慢查詢日誌,去重分析後發給你們。

         切割方法:

              1)mv ,relaod進程。2)cp,>清空

              2)利用定時任務

  以上分享內容到此結束,若有疑問歡迎發送郵件到lcp779401@cntv.cn探討交流,但願對你們有所幫助。

相關文章
相關標籤/搜索