精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何解決數據庫CPU使用率100%報警頻繁的問題呢

工程師鄧生 ? 來源:OSCHINA 社區 ? 作者:京東云開發者 ? 2022-09-01 12:12 ? 次閱讀

1 前言

近期隨著數據量的增長,數據庫 CPU 使用率 100% 報警頻繁起來。第一個想到的就是慢 Sql,我們對未合理運用索引的表加入索引后,問題依然沒有得到解決,深入排查時,發現在 order by id asc limit n 時,即使 where 條件已經包含了覆蓋索引,優化器還是選擇了錯誤的索引導致。通過查詢大量資料,問題得到了解決。這里將解決問題的思路以及排查過程分享出來,如果有錯誤歡迎指正。

2 正文

2.1 環境介紹

690987da-292c-11ed-ba43-dac502259ad0.png

2.2 發現問題

22 日開始,收到以下圖 1 報警變得頻繁起來,由于數據庫中會有大數據推數動作,數據庫 CPU 偶爾報警并沒有引起對該問題的重視,直到通過圖 2 對整日監控數據分析時,才發現問題的嚴重性,從 0 點開始,數據庫 CPU 頻繁被打滿。

691d470c-292c-11ed-ba43-dac502259ad0.png

圖 1:報警圖

692f59f6-292c-11ed-ba43-dac502259ad0.png

圖 2:整日 CPU 監控圖

2.3 排查問題

發現問題后,開始排查慢 Sql,發現很多查詢未添加合適的索引,經過一輪修復后,問題依然沒有得到解決,在深入排查時發現了一個奇怪現象,SQL 代碼如下(表名已經替換),比較簡單的一個單表查詢語句。

poYBAGMQMVOAOpvtAABHrDwPvaU298.jpg

看似比較簡單的查詢,但執行時長平均在 90s 以上,并且調用頻次較高。如圖 3 所示。
6942671c-292c-11ed-ba43-dac502259ad0.png

圖 3:慢 Sql 平均執行時長 開始檢查表信息,可以看到表數據量在 2100w 左右。

69682524-292c-11ed-ba43-dac502259ad0.png

圖 4:數據表情況 排查索引情況,主鍵為 id,并且有 business_day 與 full_ps_code 的聯合索引。

pYYBAGMQMXKAJKg_AAC5df4wQwY672.jpg

通過 Explain 查看執行計劃時發現,possible_keys 中包含上面的聯合索引,而 Key 卻選擇了 Primary 主鍵索引,掃描行數 Rows 為 1700w,幾乎等于全表掃描。 697ffca8-292c-11ed-ba43-dac502259ad0.png 圖 5:執行計劃情況

2.4 解決問題

第一次,我們分析是,由于 Where 條件中包含了 ID,查詢分析器認為主鍵索引掃描行數會少,同時根據主鍵排序,使用主鍵索引會更加合理,我們試著添加以下索引,想要讓查詢分析器命中我們新加的索引。

ADD INDEX `idx_test`(`business_day`, `full_ps_code`, `id`) USING BTREE;
再次通過 Explain 語句進行分析,發現執行計劃完全沒變,還是走的主鍵索引。

poYBAGMQNrmAAXD5AABV73g3LmY369.jpg

69999f8c-292c-11ed-ba43-dac502259ad0.png

圖 6:執行計劃情況 第二次,我們通過強制指定索引方式 force index (idx_test) 方式,再次分析執行情況,得到圖 7 的結果,同樣的查詢條件同樣的結果,查詢時長由 90s->0.49s 左右。問題得到解決

69b4bd44-292c-11ed-ba43-dac502259ad0.png

圖 7:強制指定索引后執行計劃情況

69d0761a-292c-11ed-ba43-dac502259ad0.png

第三次,我們懷疑是 where 條件中有 ID 導致直接走的主鍵索引,where 條件中去掉 id,Sql 調整如下,然后進行分析。依然沒有命中索引,掃描 rows 變成 111342,查詢時間 96s

pYYBAGMQNt-AKsWhAABGpuLdlpQ556.jpg

69ebc4f6-292c-11ed-ba43-dac502259ad0.png

69fe5170-292c-11ed-ba43-dac502259ad0.png

第四次,我們把 order by 去掉,SQL 調整如下,然后進行分析。命中了 idx_business_day_full_ps_code 之前建立的聯合索引。掃描行數變成 154900,查詢時長變為 0.062s,但是發現結果與預想的不一致,發生了亂序

pYYBAGMQNv6Adm2NAABQ1mQ72mw386.jpg

6a19bab4-292c-11ed-ba43-dac502259ad0.png


6a30d938-292c-11ed-ba43-dac502259ad0.png

第五次,經過前幾次的分析可以確定,order by 導致查詢分析器選擇了主鍵索引,我們在 Order by 中增加排序字段,將 Sql 調整如下,同樣可以命中我們之前的聯合索引,查詢時長為 0.034s,由于先按照主鍵排序,結果是一致的。相比第四種方法多了一份 filesort,問題得解決。

poYBAGMQNxyALd7yAABV3WGs9aw362.jpg

6a475fb4-292c-11ed-ba43-dac502259ad0.png
6a53257e-292c-11ed-ba43-dac502259ad0.png

第六次,我們考慮是不是 Limit 導致的問題,我們將 Limit 500 調整到 1000,Sql 調整如下,奇跡發生了,命中了聯合索引,查詢時長為 0.316s,結果一致,只不過多返回來 500 條數據。問題得到了解決。經過多次實驗 Limit 大于 695 時就會命中聯合索引,查詢條件下的數據量是 79963,696/79963 大概占比是 0.0087,猜測當獲取數據比超過 0.0087 時,會選擇聯合索引,未找到源代碼驗證此結論。

pYYBAGMQNziAI8UWAABXKmVwUbE843.jpg

6a7287ac-292c-11ed-ba43-dac502259ad0.png

6a87f5f6-292c-11ed-ba43-dac502259ad0.png

經過我們的驗證,其中第 2、5、6 三種方法都可以解決性能問題。為了不影響線上,我們立即修改代碼,并選擇了 force index 的方式,上線觀察一段時間后,數據庫 CPU 恢復正常,問題得到了解決。

6a9a7802-292c-11ed-ba43-dac502259ad0.png

3 事后分析

上線后問題得到了解決,同時也留給我了很多疑問。

為什么明明 where 條件中包含了聯合索引,卻未能命中,反而選擇了性能較慢的主鍵索引?

為什么在 order by 中增加了一個索引其他字段,就可以命中聯合索引了呢?

為什么我僅僅是將 limit 限制條件由原來的 500 調大后,也能命中聯合索引呢?

這一切的答案都來自 MySQL 的查詢優化器。

3.1 查詢優化器

查詢優化器是專門負責優化查詢語句的優化器模塊,通過計算分析收集的各種系統統計信息,為查詢給出最優的執行計劃 —— 最優的數據檢索方式。 優化器決定如何執行查詢的方式是基于一種稱為基于代價的優化的方法。5.7 在代價類型上分為 IO、CPU、Memory。內存的代價收集了,但是并沒有參與最終的代價計算。Mysql 中引入了兩個系統表,mysql.server_cost 和 mysql.engine_cost,server_cost 對應 CPU 的代價,engine_cost 代表 IO 的代價。 server_cost(CPU 代價)

row_evaluate_cost (default 0.2) 計算符合條件的行的代價,行數越多,此項代價越大

memory_temptable_create_cost (default 2.0) 內存臨時表的創建代價

memory_temptable_row_cost (default 0.2) 內存臨時表的行代價

key_compare_cost (default 0.1) 鍵比較的代價,例如排序

disk_temptable_create_cost (default 40.0) 內部 myisam 或 innodb 臨時表的創建代價

disk_temptable_row_cost (default 1.0) 內部 myisam 或 innodb 臨時表的行代價

由上可以看出創建臨時表的代價是很高的,尤其是內部的 myisam 或 innodb 臨時表。 engine_cost(IO 代價)

io_block_read_cost (default 1.0) 從磁盤讀數據的代價,對 innodb 來說,表示從磁盤讀一個 page 的代價

memory_block_read_cost (default 1.0) 從內存讀數據的代價,對 innodb 來說,表示從 buffer pool 讀一個 page 的代價

這些信息都可以在數據庫中配置,當數據庫中未配置時,從 MySql 源代碼(5.7)中可以看到以上默認值情況

6ab9aaf6-292c-11ed-ba43-dac502259ad0.png

3.2 代價配置

poYBAGMQN2KAGZiXAABiuFnB6hE024.jpg

3.3 代價計算

代價是如何算出來的呢,通過讀 MySql 的源代碼,可以找到最終的答案 3.3.1 全表掃描(table_scan_cost) 以下代碼摘自 MySql Server(5.7 分支),全表掃描時,IO 與 CPU 的代價計算方式。

poYBAGMQN4OAI0MjAAE_FZ2z7ls735.jpg
pYYBAGMQN4uAHQ0zAADlMtj10YI285.jpg

根據源代碼分析,當表中包含 100 行數據時,全表掃描的成本為 23.1,計算邏輯如下

poYBAGMQN52AMqygAABZDU0N6c8455.jpg

驗證結果如下圖

6ad746ba-292c-11ed-ba43-dac502259ad0.png

3.3.2 索引掃描(index_scan_cost) 以下代碼摘自 MySql Server(5.7 分支),當出現索引掃描時,是如何進行計算的,核心代碼如下

pYYBAGMQN8iAKhoGAABfHEGQbbs544.jpg

io 代價計算核心代碼

//核心代碼
const double io_cost= index_only_read_time(index, rows) *
table->cost_model()->page_read_cost_index(index, 1.0);

// index_only_read_time(index, rows)
// 估算index占page個數

//page_read_cost_index(index, 1.0)
//根據buffer pool大小和索引大小來估算page in memory和in disk的比例,計算讀一個page的代價

cpu 代價計算核心代碼

pYYBAGMQN_OAAgS5AABfhflMzRE733.jpg


3.3.3 其他方式 計算代價的方式有很多,其他方式請參考 MySql 原代碼。https://github.com/mysql/mysql-server.git

3.4 深度解析

通過查看 optimizer_trace,可以了解查詢優化器是如何選擇的索引。

pYYBAGMQOAqAd6a5AAClSllMXjo610.jpg

通過分析 rows_estimation 節點,可以看到通過全表掃描(table_scan)的話的代價是 8.29e6,同時也可以看到該查詢可以選擇到主鍵索引與聯合索引,如下圖。

6af7ba26-292c-11ed-ba43-dac502259ad0.png

上圖中全表掃描的代價是 8.29e6,我們轉換成普通計數法為 8290000,如果使用主鍵索引成本是 3530000,聯合索引 185881,最小的應該是 185881 聯合索引,也可以看到第一步通過成本分析確實選擇了我們的聯合索引。

6b1a2052-292c-11ed-ba43-dac502259ad0.png

6b2c6622-292c-11ed-ba43-dac502259ad0.png

6b3f857c-292c-11ed-ba43-dac502259ad0.png

但是為什么還是選擇了主鍵索引呢? 通過往下看,在 reconsidering_access_paths_for_index_ordering 節點下, 發現由于 Order by 導致重新選擇了索引,在下圖中可以看到主鍵索引可用(usable=true),我們的聯合索引為 not_applicable (不適用),意味著排序只能使用主鍵索引。

6b5f31c4-292c-11ed-ba43-dac502259ad0.png

接下來通過 index_order_summary 可以看出,執行計劃最終被調整,由原來的聯合索引改成了主鍵索引,就是說這個選擇無視了之前的基于索引成本的選擇。

6b8978bc-292c-11ed-ba43-dac502259ad0.png

為什么會有這樣的一個選項呢,主要原因如下:

The short explanation is that the optimizer thinks — or should I say hopes — that scanning the whole table (which is already sorted by the id field) will find the limited rows quick enough, and that this will avoid a sort operation. So by trying to avoid a sort, the optimizer ends-up losing time scanning the table.

從這段解釋可以看出主要原因是由于我們使用了 order by id asc 這種基于 id 的排序寫法,優化器認為排序是個昂貴的操作,所以為了避免排序,并且它認為 limit n 的 n 如果很小的話即使使用全表掃描也能很快執行完,所以它選擇了全表掃描,也就避免了 id 的排序。

5 總結

查詢優化器會基于代價來選擇最優的執行計劃,但由于 order by id limit n 的存在,MySql 可能會重新選擇一個錯誤的索引,忽略原有的基于代價選擇出來的索引,轉而選擇全表掃描的主鍵索引。這個問題在國內外有大量的用戶反饋,BUG 地址https://bugs.mysql.com/bug.php?id=97001。官方稱在 5.7.33 以后版本可以關閉 prefer_ordering_index 來解決。如下圖所示。

6ba69b36-292c-11ed-ba43-dac502259ad0.png

另外在我們日常慢 Sql 調優時,可以通過以下兩種方式,了解更多查詢優化器選擇過程。

poYBAGMQOFyAZk2CAACQfGRgS0c916.jpg

當你也出現了本篇文章碰到的問題時,可以采用以下的方法來解決

使用 force index,強制指定索引。

order by 中增加一個聯合索引的 key。

擴大 limit 返回的范圍(不推薦,隨著數據量的增大,可能還會走回主鍵索引)

order by (id+0) asc 欺騙查詢優化器,讓其選擇聯合索引。

MySQL 5.7.33 版本以上,可以關閉 prefer_ordering_index 解決。



審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • cpu
    cpu
    +關注

    關注

    68

    文章

    10825

    瀏覽量

    211150
  • SQL
    SQL
    +關注

    關注

    1

    文章

    760

    瀏覽量

    44076
  • 數據庫
    +關注

    關注

    7

    文章

    3765

    瀏覽量

    64276

原文標題:記錄一次數據庫CPU被打滿的排查過程

文章出處:【微信號:OSC開源社區,微信公眾號:OSC開源社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    數據庫數據恢復—通過拼接數據庫碎片恢復SQLserver數據庫

    一個運行在存儲上的SQLServer數據庫,有1000多個文件,大小幾十TB。數據庫每10天生成一個NDF文件,每個NDF幾百GB大小。數據庫包含兩個LDF文件。 存儲損壞,數據庫
    的頭像 發表于 10-31 13:21 ?141次閱讀
    <b class='flag-5'>數據庫</b><b class='flag-5'>數據</b>恢復—通過拼接<b class='flag-5'>數據庫</b>碎片恢復SQLserver<b class='flag-5'>數據庫</b>

    數據庫數據恢復—SQL Server數據庫出現823錯誤的數據恢復案例

    SQL Server數據庫故障: SQL Server附加數據庫出現錯誤823,附加數據庫失敗。數據庫沒有備份,無法通過備份恢復數據庫
    的頭像 發表于 09-20 11:46 ?287次閱讀
    <b class='flag-5'>數據庫</b><b class='flag-5'>數據</b>恢復—SQL Server<b class='flag-5'>數據庫</b>出現823錯誤的<b class='flag-5'>數據</b>恢復案例

    JAVA應用CPU跳點自動DUMP工具

    問題。如果CPU使用率過高,可能表示系統存在資源瓶頸,需要進行優化或升級。 CPU監控的難點 現有的監控平臺提供了多種方式來獲取容器和JVM的CPU
    的頭像 發表于 08-05 17:48 ?479次閱讀

    恒訊科技全面解析:如何有效降低服務器CPU用率

    降低服務器CPU用率是一個涉及監控、診斷和優化的全面過程。以下是一些有效的方法: 1、監控CPU使用率: 使用工具如top, htop, vmstat, 或 iostat實時監控
    的頭像 發表于 05-10 17:24 ?679次閱讀

    數據庫數據恢復—raid5陣列上層Sql Server數據庫數據恢復案例

    數據庫數據恢復環境: 5塊硬盤組建一組RAID5陣列,劃分LUN供windows系統服務器使用。windows系統服務器內運行了Sql Server數據庫,存儲空間在操作系統層面劃分了三個邏輯分區
    的頭像 發表于 05-08 11:43 ?476次閱讀
    <b class='flag-5'>數據庫</b><b class='flag-5'>數據</b>恢復—raid5陣列上層Sql Server<b class='flag-5'>數據庫</b><b class='flag-5'>數據</b>恢復案例

    數據庫數據恢復】Oracle數據庫ASM實例無法掛載的數據恢復案例

    oracle數據庫ASM磁盤組掉線,ASM實例不能掛載。數據庫管理員嘗試修復數據庫,但是沒有成功。
    的頭像 發表于 02-01 17:39 ?477次閱讀
    【<b class='flag-5'>數據庫</b><b class='flag-5'>數據</b>恢復】Oracle<b class='flag-5'>數據庫</b>ASM實例無法掛載的<b class='flag-5'>數據</b>恢復案例

    如何在Linux系統中檢查CPU使用率

    首先在Linux系統中檢查CPU使用率。可以通過在命令行中輸入top或htop命令來查看當前系統中各個進程的CPU使用率。如果CPU
    發表于 01-06 10:42 ?1272次閱讀
    如何在Linux系統中檢查<b class='flag-5'>CPU</b><b class='flag-5'>使用率</b>

    無模式數據庫的利與弊

    數據管理需求日益多樣,無論是金融服務、游戲還是社交媒體行業,都要求支持實時數據處理和快速迭代,無模式數據庫因其靈活性和易用性而逐漸成為開發者的新選擇。那么,無模式數據庫到底有哪些特性
    的頭像 發表于 12-16 08:04 ?482次閱讀
    無模式<b class='flag-5'>數據庫</b>的利與弊

    數據庫數據恢復—未開啟binlog的Mysql數據庫數據恢復案例

    mysql數據庫數據恢復環境: 本地服務器,windows server操作系統 ,部署有mysql單實例,數據庫引擎類型為innodb,獨立表空間,無數據庫備份,未開啟binlog
    的頭像 發表于 12-08 14:18 ?1094次閱讀
    <b class='flag-5'>數據庫</b><b class='flag-5'>數據</b>恢復—未開啟binlog的Mysql<b class='flag-5'>數據庫</b><b class='flag-5'>數據</b>恢復案例

    關于JSON數據庫

    如何理解JSON數據庫?作為NoSQL數據庫的一種類型,JSON數據庫有哪些優勢?JSON數據庫如何運作,它為應用程序開發者帶來了哪些價值
    的頭像 發表于 12-06 13:46 ?838次閱讀
    關于JSON<b class='flag-5'>數據庫</b>

    mysql數據庫基礎命令

    MySQL是一個流行的關系型數據庫管理系統,經常用于存儲、管理和操作數據。在本文中,我們將詳細介紹MySQL的基礎命令,并提供與每個命令相關的詳細解釋。 登錄MySQL 要登錄MySQL數據庫,可以
    的頭像 發表于 12-06 10:56 ?552次閱讀

    oracle數據庫的基本操作

    Oracle數據庫是一種關系數據庫管理系統(RDBMS),廣泛應用于企業級應用中。它具有強大的功能和靈活的配置選項,可以滿足復雜的數據處理需求。本文將介紹Oracle數據庫的基本操作,
    的頭像 發表于 12-06 10:14 ?661次閱讀

    Java程序CPU使用率高的原因

    Java程序是一種高級編程語言,由于其跨平臺的特性和強大的功能,被廣泛應用于服務器端、企業級應用和大數據處理等場景。然而,在某些情況下,我們可能會發現Java程序的CPU使用率異常高,這會導致系統
    的頭像 發表于 12-05 11:20 ?5234次閱讀

    什么是JSON數據庫

    如何理解JSON數據庫?作為NoSQL數據庫的一種類型,JSON數據庫有哪些優勢?JSON數據庫如何運作,它為應用程序開發者帶來了哪些價值
    的頭像 發表于 12-02 08:04 ?826次閱讀
    什么是JSON<b class='flag-5'>數據庫</b>

    NoSQL 數據庫如何選型

    什么是NoSQL數據庫?為什么要使用NoSQL數據庫?鍵值數據庫內存鍵值數據庫文檔數據庫列式數據庫
    的頭像 發表于 11-26 08:05 ?446次閱讀
    NoSQL <b class='flag-5'>數據庫</b>如何選型