程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> MySQL的一條慢SQL查詢招致全部網站宕機的處理辦法

MySQL的一條慢SQL查詢招致全部網站宕機的處理辦法

編輯:MySQL綜合教程

MySQL的一條慢SQL查詢招致全部網站宕機的處理辦法。本站提示廣大學習愛好者:(MySQL的一條慢SQL查詢招致全部網站宕機的處理辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是MySQL的一條慢SQL查詢招致全部網站宕機的處理辦法正文


直接切入正題吧:

平日來講,我們看到的慢查詢普通還不致於招致掛站,頂多就是運用呼應變慢
不外這個正好明天被我撞見了,一個慢查詢把全部網站弄掛了
先看看這個SQL張撒模樣:

# Query_time: 70.472013 Lock_time: 0.000078 Rows_sent: 7915203 Rows_examined: 15984089 Rows_affected: 0
# Bytes_sent: 1258414478
use js_sku;
SET timestamp=1465850117;
SELECT 
ss_id, ss_sa_id, ss_si_id, ss_av_zid, ss_av_fid, ss_artno,
ss_av_zvalue, ss_av_fvalue, ss_av_zpic, ss_av_fpic, ss_number,
ss_sales, ss_cprice, ss_price, ss_stock, ss_orderid, ss_status,
ss_add_time, ss_lastmodify
FROM js_sgoods_sku
WHERE ss_si_id = 0 AND ss_status > 0
ORDER BY
ss_orderid DESC, ss_av_fid ASC;
這裡貼出來的就是 mysql slow log 的信息,查詢時光用了高達 70s!!
看到慢查詢我們普通第一反響是這個 語句沒有效到索引? 或許是索引不公道麼? 那我們會去看看履行籌劃:

mysql> explain SELECT 
-> ss_id, ss_sa_id, ss_si_id, ss_av_zid, ss_av_fid, ss_artno,
-> ss_av_zvalue, ss_av_fvalue, ss_av_zpic, ss_av_fpic, ss_number,
-> ss_sales, ss_cprice, ss_price, ss_stock, ss_orderid, ss_status,
-> ss_add_time, ss_lastmodify
-> FROM js_sgoods_sku
-> WHERE ss_si_id = 0 AND ss_status > 0
-> ORDER BY
-> ss_orderid DESC, ss_av_fid ASC;
+----+-------------+---------------+------+---------------+----------+---------+-------+---------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+------+---------------+----------+---------+-------+---------+-----------------------------+
| 1 | SIMPLE | js_sgoods_sku | ref | ss_si_id | ss_si_id | 4 | const | 9516091 | Using where; Using filesort |
+----+-------------+---------------+------+---------------+----------+---------+-------+---------+-----------------------------+
1 row in set (0.00 sec)

這個看起來仿佛用到了索引,可是為何掃描到行照樣這麼多呢? 那我們就去看看表構造了,希冀能從中找到點有價值的器械:
我們看到以下可用信息:
KEY `ss_si_id` (`ss_si_id`,`ss_av_zid`,`ss_av_fid`) USING BTREE,
`ss_si_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '對應js_sgoods_info.si_id',

我們看到 索引仿佛還能比擬可以或許接收,然則我們看到 這個 ss_si_id 這個字段現實上是 goods_info 表的主鍵,也就是說它的團圓水平應當是很年夜的,也就是辨別度很年夜。
其實到這一步我們根本上可以以為 是因為我們這個內外邊有許多 ss_si_id=0 招致,不外我們可以進一步的來證明我們的料想:

1. 起首我們可以先肯定我們的統計信息沒有成績
2. 其次我們再count ss_si_id=0 的這個值有若干數據,來進一步驗證我們的料想。

那末我們先檢查以下這個索引的統計信息:
xiean@localhost:js_sku 03:27:42>show index from js_sgoods_sku;
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| js_sgoods_sku | 0 | PRIMARY | 1 | ss_id      | A | 18115773 | NULL | NULL | | BTREE | | |
| js_sgoods_sku | 1 | ss_si_id | 1 | ss_si_id   | A  | 1811577  | NULL | NULL | | BTREE | | |
| js_sgoods_sku | 1 | ss_si_id | 2 | ss_av_zid | A | 6038591  | NULL | NULL | | BTREE | | |
| js_sgoods_sku | 1 | ss_si_id | 3 | ss_av_fid | A | 18115773 | NULL | NULL | | BTREE | | |
| js_sgoods_sku | 1 | IDX_001 | 1 | ss_sa_id | A | 3623154   | NULL | NULL | | BTREE | | |
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

那末可以看到以下成績:
我們的ss_si_id 這個字段並沒有我們外面上看到的 由於聯系關系了某個表的主鍵,它的Cardinality 值就應當接近於 PRIMARY 的值。而是差異比擬年夜的,豈非是 索引的統計信息禁絕確? 那我們測驗考試從新搜集下索引的統計信息:
xiean@localhost:js_sku 03:27:47>analyze table js_sgoods_sku;
+----------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+----------------------+---------+----------+----------+
| js_sku.js_sgoods_sku | analyze | status | OK |
+----------------------+---------+----------+----------+

but ,我們再次檢查 這些索引的統計信息:
xiean@localhost:js_sku 03:28:14>show index from js_sgoods_sku;
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| js_sgoods_sku | 0 | PRIMARY | 1 | ss_id      | A | 18621349 | NULL | NULL | | BTREE | | |
| js_sgoods_sku | 1 | ss_si_id | 1 | ss_si_id    | A | 1551779  | NULL | NULL | | BTREE | | |
| js_sgoods_sku | 1 | ss_si_id | 2 | ss_av_zid | A | 6207116   | NULL | NULL | | BTREE | | |
| js_sgoods_sku | 1 | ss_si_id | 3 | ss_av_fid | A | 18621349 | NULL | NULL | | BTREE | | |
| js_sgoods_sku | 1 | IDX_001 | 1 | ss_sa_id | A | 3724269   | NULL | NULL | | BTREE | | |
+---------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

我們可以看到 ss_si_id 的團圓水平(Cardinality) 沒有增長反而有向下動搖的趨向,由於這個信息是收集部門頁的來的,而每一個頁上邊數據散布是紛歧樣的,招致我們這個索引搜集的統計信息就回有所變更。

好吧,到這裡我們可以以為我們的 統計信息沒有掉效,那末我們就看數據的分離情形咯:

+--------------++----------++------------------+
| ss_si_id=0; || count(*) || 7994788/19048617 |
+--------------++----------++------------------+
| 7994788     || 19048617 ||    0.4197           |
+--------------++----------++------------------+

額,不看不曉得,一看嚇一跳:我們這個內外邊 存在有年夜量的 ss_si_id=0 的情形,占了全部表數據量的 41% !!!


好吧成績找到了,那末接上去我們須要曉得,為何這個SQL語句會招致掛站呢?

我們經由過程不雅看運用法式辦事器的監控看到一些信息:我們的 goods_service 這個辦事異常:異常情形以下:

1. cpu 歷久占用100% + 
2. jstatck pid 沒法dump 內存客棧信息,必需強迫dump -F
3. dump 出來的內存信息發明,這個過程裡邊一切線程 均處於 BLOCKED 狀況
4. 經由過程jstat -gcutil 看到 FGC 相當頻仍,10s閣下就FGC一次
5. 內存占用跨越了分派的內存

那末終究的緣由就是由於上邊的慢查詢 查詢了年夜量數據(最多有700w行數據),招致goods_service 內存暴跌,湧現辦事沒法呼應,進一步的好轉就是掛占


OK,曉得了為何會掛占,那末我們是若何處理這個成績的呢?
既然我們曉得是因為查詢了 ss_si_id=0 招致的,那末我們屏障失落這個SQL不就行了麼。屏障的方法可以有多種:
1. 我們法式邏輯斷定一下這類型的 查詢 假如 有查詢 ss_si_id=0 的一概封殺失落
2. 我們改改SQL設置裝備擺設文件,修正SQL語句

我們發明DB辦事器上存在年夜量的 這個慢查詢,並且DB辦事器負載曾經從 0.xx 飙升到了 50+ 了,隨之而來的銜接數也飙升的凶猛, 假如再不實時處置,估量DB辦事器也掛失落了

 

那末我們終究采用以下處置方法:
1.運維合營研發修正SQL語句 我們在這個WHERE 前提中添加了一個前提: AND ss_si_id <> 0 ,在MySQL之行籌劃層屏障失落此SQL;
2.DBA 開啟kill 失落這個查詢語句,防止DB辦事器湧現down機的情形,固然這個就用到了我們的 pt-kill 對象,不能不說這個對象相當好用


總結(經歷與經驗):
1.相似這類查詢 default 值的 SQL ,我們應當從泉源上根絕這類查詢
2.限制查詢成果集年夜小,防止因查詢成果集太年夜招致辦事逝世失落

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved