MySQL實戰45講 19

来源:https://www.cnblogs.com/ydssx7/archive/2022/07/28/16530137.html
-Advertisement-
Play Games

19 | 為什麼我只查一行的語句,也執行這麼慢? 有些情況下,“查一行”,也會執行得特別慢。 需要說明的是,如果 MySQL 資料庫本身就有很大的壓力,導致資料庫伺服器 CPU 占用率很高或 ioutil(IO 利用率)很高,這種情況下所有語句的執行都有可能變慢,不屬於本章討論範圍。 為了便於描述, ...


19 | 為什麼我只查一行的語句,也執行這麼慢?

有些情況下,“查一行”,也會執行得特別慢。

需要說明的是,如果 MySQL 資料庫本身就有很大的壓力,導致資料庫伺服器 CPU 占用率很高或 ioutil(IO 利用率)很高,這種情況下所有語句的執行都有可能變慢,不屬於本章討論範圍。

為了便於描述,構造一個表,基於這個表來說明問題。這個表有兩個欄位 id 和 c,並且在裡面插入了 10 萬行記錄。

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `c` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
 
delimiter ;;
create procedure idata()
begin
  declare i int;
  set i=1;
  while(i<=100000)do
    insert into t values(i,i);
    set i=i+1;
  end while;
end;;
delimiter ;
 
call idata();

第一類:查詢長時間不返回

在表 t 執行下麵的 SQL 語句:

select * from t where id=1;

查詢結果長時間不返回。

image-20220728170411761

一般碰到這種情況的話,大概率是表 t 被鎖住了。接下來分析原因的時候,一般都是首先執行一下 show processlist 命令,看看當前語句處於什麼狀態。

然後再針對每種狀態,去分析它們產生的原因、如何復現,以及如何處理。

等 MDL 鎖

下圖就是使用 show processlist 命令查看 Waiting for table metadata lock 的示意圖。

出現這個狀態表示的是,現在有一個線程正在表 t 上請求或者持有 MDL 寫鎖,把 select 語句堵住了。

復現這個場景

session A 通過 lock table 命令持有表 t 的 MDL 寫鎖,而 session B 的查詢需要獲取 MDL 讀鎖所以,session B 進入等待狀態

這類問題的處理方式,就是找到誰持有 MDL 寫鎖,然後把它 kill 掉。

但是,由於在 show processlist 的結果裡面,session A 的 Command 列是“Sleep”,導致查找起來很不方便。不過有了 performance_schema 和 sys 系統庫以後,就方便多了。(MySQL 啟動時需要設置 performance_schema=on,相比於設置為 off 會有 10% 左右的性能損失)

通過查詢 sys.schema_table_lock_waits 這張表,我們就可以直接找出造成阻塞的 process id,把這個連接用 kill 命令斷開即可

等 flush

另外一種查詢被堵住的情況

在表 t 上,執行下麵的 SQL 語句:

select * from information_schema.processlist where id=1;

查出來這個線程的狀態是 Waiting for table flush,這個狀態表示的是,現在有一個線程正要對錶 t 做 flush 操作

MySQL 裡面對錶做 flush 操作的用法,一般有以下兩個:

flush tables t with read lock;
 
flush tables with read lock;

這兩個 flush 語句,如果指定表 t 的話,代表的是只關閉表 t;如果沒有指定具體的表名,則表示關閉 MySQL 里所有打開的表。

正常這兩個語句執行起來都很快,除非它們也被別的線程堵住了。

所以,出現 Waiting for table flush 狀態的可能情況是:有一個 flush tables 命令被別的語句堵住了,然後它又堵住了我們的 select 語句。

復現一下這種情況,復現步驟如下圖所示:

在 session A 中,故意每行都調用一次 sleep(1),這樣這個語句預設要執行 10 萬秒,在這期間表 t 一直是被 session A“打開”著。然後,session B 的 flush tables t 命令再要去關閉表 t,就需要等 session A 的查詢結束。這樣,session C 要再次查詢的話,就會被 flush 命令堵住了。

等行鎖

select * from t where id=1 lock in share mode; 

由於訪問 id=1 這個記錄時要加讀鎖,如果這時候已經有一個事務在這行記錄上持有一個寫鎖, select 語句就會被堵住。

行鎖復現步驟和現場如下:

行鎖 show processlist 現場如下圖:

顯然,session A 啟動了事務,占有寫鎖,還不提交,是導致 session B 被堵住的原因。

這個問題並不難分析,但問題是怎麽查出是誰占著這個寫鎖。???(待解決)

mysql 查看誰在持有鎖

show engine innodb status查看,但是它只顯示誰在等待鎖,無法查看到誰持有鎖;

第二類:查詢慢

掃描行數多,所以執行慢

select * from t where c=50000 limit 1;

由於欄位 c 上沒有索引,這個語句只能走 id 主鍵順序掃描,因此需要掃描 5 萬行。

作為確認,可以看一下慢查詢日誌。這裡為了把所有語句記錄到 slow log 里,在連接後先執行了 set long_query_time=0將慢查詢日誌的時間閾值設置為 0

下圖為全表掃描 5 萬行的 slow log

Rows_examined 顯示掃描了 50000 行。不是很慢呀,11.5 毫秒,線上一般都配置超過 1 秒才算慢查詢。但要記住:壞查詢不一定是慢查詢。這個例子裡面只有 10 萬行記錄,數據量大起來的話,執行時間就線性漲上去了。

掃描一行卻執行得很慢

select * from t where id=1;

雖然掃描行數是 1,但執行時間卻長達 800 毫秒。

下一個語句

select * from t where id=1 lock in share mode

執行時掃描行數也是 1 行,執行時間是 0.2 毫秒

Q:按理說 lock in share mode 還要加鎖,時間應該更長才對,為什麼?

A:

下圖是這兩個語句的執行輸出結果。

第一個語句的查詢結果里 c=1,帶 lock in share mode 的語句返回的是 c=1000001。

復現步驟

session A 先用 start transaction with consistent snapshot 命令啟動了一個事務,之後 session B 才開始執行 update 語句。

session B 執行完 100 萬次 update 語句後id狀態如下:

session B 更新完 100 萬次,生成了 100 萬個回滾日誌 (undo log)。

帶 lock in share mode 的 SQL 語句,是當前讀,因此會直接讀到 1000001 這個結果,所以速度很快;而 select * from t where id=1 這個語句,是一致性讀因此需要從 1000001 開始,依次執行 undo log,執行了 100 萬次以後,才將 1 這個結果返回。

PS:undo log 里記錄的其實是“把 2 改成 1”,“把 3 改成 2”這樣的操作邏輯,畫成減 1 的目的是方便看圖。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • GraphPad Prism 9 for Mac是一款專業的科研統計分析繪圖軟體,世界領先的科學家都在使用Prism 9 Mac,使用Prism 9 Mac版幫助您有效的分析、統計並繪製出直觀的圖形,幫您節省大量的時間,讓您更加專註於您的科研。 詳情:GraphPad Prism 9 for Mac ...
  • 前言 製作centos7無人值守安裝,在windows下也可以進行,但是由於U盤文件系統的問題,難免需要在windows和centos7下來回切換,進行配置,才能完成製作,比如主分區exfat格式用於存放ISO和ks.cfg文件通常情況下只能被windows讀取,centos7下讀取不到,掛載不上, ...
  • DxO PureRAW Mac版是發佈了,該軟體採用了智能技術,以解決影響所有RAW文件的七個問題:去馬賽克,降噪,波紋,變形,色差,不想要的漸暈,以及缺乏清晰度。 詳情:DxO PureRAW for mac(raw照片處理器) 功能特色 釋放Adobe Photoshop和Lightroom的R ...
  • 想給自己的照片變得高大上嗎?那就來試試這裡的DxO PhotoLab for Mac版raw圖片處理軟體吧。它可以隨時手動調整,控制照片的各個方面。dxo photolab mac版還能去除噪音有效地消除了光的限制,檢索顏色的細節,應用複雜的光學校正和增強細節。 詳情:DxO PhotoLab 5 ...
  • 換源(建議清華源或者阿裡源) sudo apt update sudo apt upgrade # 軟體升級 sudo apt dist-upgrade #內核更新 grub-customizer 引導控制工具 sudo add-apt-repository ppa:danielrichter200 ...
  • 一、電腦基礎和Linux基礎知識 1.馮諾依曼體繫結構 1946年美籍匈牙利數學家馮·諾依曼於提出存儲程式原理,把程式本身當作數據來對待,程式和該程式處理的數據用同樣的方式儲存。馮·諾依曼體系的要點是: 數字電腦的數制採用二進位,bit位, byte位元組1 byte = 8 bit 電腦應該按 ...
  • #資料庫的CRUD語句 ##INSERT語句 ###在指定列中插入數據 INSERT INTO 表名 (column1,column2,column3,...) VALUES (value1,value2,value3,...); INSERT INTO website (url,country) ...
  • 使用flink的時候難免和redis打交道,相信大家都使用過flink-connector-redis來處理,但是當我想要使用RedisSink寫入集群時,發現居然不支持使用密碼,於是有了這篇筆記。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...