爲何查詢數據很少,卻慢的離譜,在我請教了隔壁新來的阿里大佬後

本文已收錄GitHub,更有互聯網大廠面試真題,面試攻略,高效學習資料等git

這篇文章主要記錄,形成查詢數量不大的狀況下,形成查詢緩慢的緣由,以及相應的解決方法。github

環境說明:面試

MySQL 版本 5.7.27
隔離級別:RRsession

鎖等待形成查詢速度很慢

MDL 鎖

如開啓以下事務:ide

爲何查詢數據很少,卻慢的離譜,在我請教了隔壁新來的阿里大佬後

Session A 持有表 t MDL 寫鎖。Session B 須要 MDL 讀鎖。這時讀寫鎖互斥,Session B 被阻塞。性能

flush 阻塞

flush 操做通常來講很快就能執行完,當經過查詢進程狀態後,看到被 flush 操做被阻塞,通常都是由其餘語句引發的。學習

以下面事務:日誌

爲何查詢數據很少,卻慢的離譜,在我請教了隔壁新來的阿里大佬後

Session A 在掃描每一行時會休眠1s,而 Session B 的 flush tables t; 須要關閉表 t,要等 Session A 結束。後面的 Session C 被 Session B 阻塞了。code

flush 的操做示範:orm

#  flush 表 t
flush tables t with read lock;
# flush 全部表
flush tables with read lock;
flush 的做用在 全局鎖 文章中已經介紹過,FTWRL 主要用於 MyISAM 這樣不支持事務的引擎,保證在備份時視圖數據一致性。

行鎖

這裏的行鎖,用兩階段鎖來體現。其餘如間歇鎖和 next-key 鎖都會能夠形成這樣的現象。

爲何查詢數據很少,卻慢的離譜,在我請教了隔壁新來的阿里大佬後

Session A 擁有 id=1 這行的寫鎖,Session B 想要擁有這一行的讀鎖,讀寫鎖互斥。

解決方法

首先經過 show processlist; 命令查詢被阻塞的狀態信息。如需進一步分析的話,能夠將 performance_schema=on 打開,經過查詢 select blocking_pid from sys.schema_table_lock_waits; 具體形成鎖等待的緣由。而後 kill掉相應的 session.

在打開 performance_schema 會有必定的性能損失。

查詢確實慢

沒有設置合適的索引

若是沒有設置合適的索引,致使掃描行數過多,時間天然就慢了。對於這種狀況,能夠開啓慢查詢日誌,查看語句的執行過程,而後進行分析。

默認狀況,慢查詢日誌時關閉的,打開方式以下:

# 查詢慢查詢日誌狀態及存儲位置
# show variables  like '%slow_query_log%';

# 查詢慢查詢日誌的設置時間
show variables  like '%long_query%';

# 臨時打開慢查詢日誌,MySQL 重啓後失效
set global slow_query_log=1;

# 改變時間
set long_query_time=0;

事務隔離的影響

在事務究竟有沒有被隔離這篇中,咱們知道表中的每行數據都有多個版本,在一致性視圖開啓後,視圖的一致性讀的結果就是經過和數據行的版本比較進而顯示的結果。

爲何查詢數據很少,卻慢的離譜,在我請教了隔壁新來的阿里大佬後

這時第一個 select 語句就會比第二個加鎖的 select 語句還要慢。

由於第一個 select 語句是一致性讀,須要從 100 萬條回滾日誌中比較直到找到適合的版本。

而第二個 select 語句是當前讀,直接讀取最新版本就能夠了。因此花費的時間不同。

總結

形成查詢小數據量,卻很緩慢的緣由通常有兩種,第一種多是所查數據被鎖住。另外一種確實是查找過程是真的很慢。

對於數據被鎖住的狀況,通常會由 MDL 鎖,FLUSH 操做被阻塞,行鎖形成。

對於查詢確實很慢來講,考慮下索引是否設置的合適。並注意在 RR 級別下,是否因爲一致性讀和當前讀的不一樣而形成查詢速度不一致的狀況。

在分析緣由時,能夠經過進程狀態以及 sys.innodb_lock_waits 中的信息,來作出相應的處理。

相關文章
相關標籤/搜索