日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

《MySQL——查询长时间不返回的三种原因与查询慢的原因》

發(fā)布時(shí)間:2023/12/1 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《MySQL——查询长时间不返回的三种原因与查询慢的原因》 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

  • 查詢長時(shí)間不返回
    • 等MDL鎖
    • 等flush
    • 等行鎖
  • 查詢慢

構(gòu)造一張表,表有兩個(gè)字段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() begindeclare i int;set i = 1;while( i <= 100000) doinsert into t values(i,i);set i = i+1;end while; end;; delimiter ;call idata();

查詢長時(shí)間不返回

在表t執(zhí)行:

select * from t where id = 1;

查詢結(jié)果長時(shí)間不返回。

等MDL鎖

大概率是表t被鎖住了,接下來分析原因:一般都是首先執(zhí)行show processlist命令,看看當(dāng)前語句處于什么狀態(tài)。

表示現(xiàn)在有個(gè)線程正在表t上請求或者持有MDL寫鎖,把select語句阻塞了:

session A通過lock table命令持有表t的MDL寫鎖,而sessionB 的查詢需要獲取MDL讀鎖,所以session B 進(jìn)入等待狀態(tài)。

處理方式:找到誰持有MDL寫鎖,然后把它kill掉。

通過

select blocking_pid from sys.schema_table_lock_waits;

得到blocking_pid = 4;

然后用kill命令斷開即可。

等flush

在表t上執(zhí)行下面語句:

select * from information_schema.processlist where id=1;

可以查看出該線程的狀態(tài)是Waiting for table flush;

表示現(xiàn)在有一個(gè)線程正要對表t做flush操作。

flush tables t with read lock; --只關(guān)閉表t --or flush tables with read lock; --關(guān)閉MySQL里面所有打開的表

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

所以可能是:有一個(gè)flush tables命令被別的語句堵住了,然后它又堵住了我們的select語句。

下圖是執(zhí)行結(jié)果:

等行鎖

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

由于訪問id = 1這個(gè)記錄時(shí)要加讀鎖,如果這時(shí)候已經(jīng)有一個(gè)事務(wù)在這行記錄上持有一個(gè)寫鎖,我們的select語句就會(huì)被堵住,如下:

session A啟動(dòng)事務(wù),占用寫鎖,但是不提交,導(dǎo)致session B被堵住。

可以通過:

mysql> select * from t sys.innodb_lock_waits where locked_table='`test`.`t`'\G

進(jìn)行查詢,查出是誰占著這個(gè)寫鎖

發(fā)現(xiàn)是4號(hào)線程,然后我們kill 4

查詢慢

select * from t where c = 50000 limit 1;

由于字段c上沒有索引,所以這個(gè)語句只能走id主鍵順序掃描,因此需要掃描5萬行。

掃描行數(shù)多,所以執(zhí)行慢,這個(gè)很好理解。

而下面的這條語句掃描行數(shù)為1,但是執(zhí)行時(shí)間取卻較長

select * from t where id = 1;


在這個(gè)場景下,session A先啟動(dòng)了一個(gè)事務(wù),之后session B才開始執(zhí)行update語句。

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

帶lock in share mode 的sql是當(dāng)前讀,因此會(huì)直接讀到 1000001 ,所以速度很快。

select * from t where id = 1語句是一致性讀,因此需要從 1000001 開始,依次執(zhí)行undo log,執(zhí)行100萬次后,才將1返回

**回滾日志過大引起的一致性讀慢,當(dāng)前讀快 **

總結(jié)

以上是生活随笔為你收集整理的《MySQL——查询长时间不返回的三种原因与查询慢的原因》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。