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

2021-09-24 09:04:44 字數 3138 閱讀 3051

有些情況下,「查一行」也會執行的特別慢,

需要說明,如果mysql資料本身就有很大的壓力,導致資料庫伺服器cpu佔用率很高或ioutil(io利用率高)很高,這種情況下所有語句的執行都有可能變慢,不在今天的討論範圍。

示例sql(插入了10萬行記錄):

mysql> 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執行下面語句:select * from t where id = 1;

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

出現這個狀態表示的是,現在有乙個執行緒在表t上請求或者持有mdl寫鎖,把select語句堵住了。

mysql 5.7版本復現方式:

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

show processlist裡面,session a的command列是「sleep」,導致查詢起來不方便,有了performance和sys系統庫以後,就方便多了。(mysql啟動的時候需要何止performance_schema=on,相比於設定為off會有10%左右的效能損失)。

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

表t上執行下面語句:select * from information_schema.processlist where id=1;

這個狀態表示,現在有乙個執行緒正要對錶t做flush操作。mysql裡面對錶做flush操作的用法一般有以下兩個:

flush tables t with read lock;    /*只關閉表t*/

flush tables with read lock;  /*關閉mysql裡所有開啟的表*/

正常情況,這兩個語句執行都很快,除非它們也被別的執行緒堵住了。

所以,可能是有乙個flush tables命令被別的語句堵住了,然後它又堵住了我們的select語句。

復現方式:

可以通過show processlist檢視結果。

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

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

復現步驟:

如果是mysql 5.7版本,可以通過sys.innodb_lock_waits表查到是誰佔著這個寫鎖。

4號執行緒是造成堵塞的罪魁禍首,kill query 4或者kill 4。

實際上,這裡不應該顯示kill query 4。kill 4才有效。連線被斷開的時候,會自動回滾這個連線裡面正在執行的執行緒,也就釋放了id=1上的行鎖。

select * from t where c=50000 limit 1;

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

select * from t wehre id=1;

雖然是掃瞄一行,但執行時間長達800毫秒。

第二個語句,加了鎖,0.2毫秒就執行完了,按理說lock in share mode還要加鎖,時間應該更長。

兩個語句的執行輸出結果:

復現步驟:

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

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

你為什麼選擇產品經理這一行?

背景是什麼?轉產品經理的訴求是?夏陽 來了乙個穿西裝的,挨個握手說你們辛苦了,跟首長一樣。然後我們頭兒介紹說這是我們的產品經理。我一看,好牛啊,以後我也要幹產品經理,然後就現在這樣了。也發現自己當年被騙了!iamsteve 大概是這樣的,分為幾種型別 畢業生 法學畢業的 當不上律師 公務員,當產品經...

ResultSet只返回一行資料的原因

寫之前,先告戒一下自己.寫 一定要細心,自己寫的即使是非常簡單的地方也要細心,不能自我感覺太良好,那往往可能會有些bug在等著你.注意事項 1 當你為了檢視資料庫中是否存在某條記錄時,比如查詢表中是否有某賬號名,有就返回前台乙個 該賬號已註冊 的訊息。諸如此類的單查詢時,可以這麼寫 if rs.ne...

SQL中刪除重複的行 重複資料 ,只保留一行

sql中刪除重複的行 重複資料 只保留一行 方法一 使用在t sql的程式設計中 分配乙個列號碼,以col1,col2組合來分割槽排序,刪除database重複的行 重複資料 只保留一行 col1,col2是資料庫database的字段 delete a from select col1,col2,...