目錄
1、第一類:查詢長時間不返回
mysql> select * from t where id=1;
一般碰到這種情況的話,大概率是表 t 被鎖住了。
首先執行一下 show processlist 命令,看看當前語句處於什麼狀態。
(1)等 MDL 鎖
舉例:
原因:即現在有一個線程正在表 t 上請求或者持有 MDL 寫鎖,把 select 語句堵住了。
解決:通過查詢 sys.schema_table_lock_waits 這張表,我們就可以直接找出造成阻塞的 process id,把這個連接用 kill 命令斷開即可。
(2)等 flush
舉例:
原因:有一個 flush tables 命令被別的語句堵住了,然後它又堵住了我們的 select 語句。
現在有一個線程正要對錶 t 做 flush 操作。MySQL 裏面對錶做 flush 操作的用法,一般有以下兩個:
flush tables t with read lock;
flush tables with read lock;
注:這兩個 flush 語句,如果指定表 t 的話,代表的是隻關閉表 t;如果沒有指定具體的表名,則表示關閉 MySQL 裏所有打開的表
(3)等行鎖
舉例:
原因:session A 啓動了事務,佔有寫鎖,還不提交,是導致 session B 被堵住的原因。
解決:查出誰佔用行鎖,kill掉
2、第二類:查詢慢
(1)掃描行數多,所以執行慢
mysql> select * from t where c=50000 limit 1;
由於字段 c 上沒有索引,這個語句只能走 id 主鍵順序掃描,因此需要掃描 5 萬行。
(2)一致性讀需要進行多次回滾操作
只掃描一行,但是執行很慢的語句:“ select * from t where id=1;”執行時間長達 800 毫秒。而“select * from t where id=1 lock in share mode“,執行時掃描行數也是 1 行,執行時間是 0.2 毫秒
結果:爲什麼結果不一致呢?
原因:session B 更新完 100 萬次,生成了 100 萬個回滾日誌 (undo log)。帶 lock in share mode 的 SQL 語句,是當前讀,因此會直接讀到 1000001 這個結果,所以速度很快;而 select * from t where id=1 這個語句,是一致性讀,因此需要從 1000001 開始,依次執行 undo log,執行了 100 萬次以後,纔將 1 這個結果返回。