mysql 如何判斷SQL語句觸發的行鎖還是表鎖?


1.情景展示

  我們知道,當在對表執行新增、修改、刪除,或者select ...for update時,會觸發數據庫的鎖機制;

  但如何才能知道當前操作觸發的是哪種鎖呢?以mysql為例

2.分析

  首先,我們需要了解一下mysql的鎖機制:

  鎖是計算機協調多個進程或線程並發訪問某一資源的機制。

  在mysql中,鎖可以分為:行鎖和表鎖兩種類型;

  其次,需要確定默認存儲引擎。

  MyISAM存儲引擎:只支持表鎖(table-level locking);

  MEMORY存儲引擎:只支持表鎖(table-level locking);

  BDB存儲引擎:支持頁面鎖,也支持表級鎖,已被InnoDB取代(page-level locking);

  InnoDB存儲引擎:支持行鎖和表鎖,默認使用行鎖(row-level locking)。

  需要確定mysql當前正在使用的是存儲引擎是不是InnoDB,只有InnoDB才支持行鎖;

  鎖特點:

  原理:

  InnoDB行鎖是通過給索引上的索引項加鎖來實現的,這一點MySQL與Oracle不同,后者是通過在數據塊中對相應數據行加鎖來實現的。

  InnoDB這種行鎖實現特點意味着:只有通過索引條件檢索數據,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖!!!(下面一起來驗證一下)  

3.解決方案

  辦法:

  可以來兩個事務,一個修改某一行數據,先別提交,然后另一個事務去修改別的行數據,如果不阻塞那應該就是行鎖,否則就是表鎖。

  前提:

  關閉mysql的自動提交事務;

  在Navicat中,要想進行鎖測試,必須關掉mysql的自動提交事務機制,實現方式見文末推薦。

  先來驗證mysql是不是由索引觸發的行鎖?

  第一步:驗證表鎖

  此時,表中沒有任何一個索引。

  此時當前號為

  更新第一行記錄,但並未提交事務。

  此時來看表數據是否發生變化

  點擊底部刷新按鈕,數據並未變化;

  現在,更新第二條記錄,並立刻提交。

  我們會發現,它一直處於執行狀態,如果時間過長,當前事務被迫中止,結果就是更新失敗。 

  我們需要重新執行更新並提交才行,這次,不能再等待這么長時間,之所以這樣弄,是為了方便讓大家看效果。

  這次,重新執行第二條更新語句,此時第一條更新語句還沒有提交:

  提交第一條更新語句;

  此時,隔壁也會立刻提交完畢。

  此時,兩條記錄都已+1。

  如此說來,也就證明了上面的觀點的前半句:

  如果where條件沒有索引,觸發的將是表索引。

  第二步:驗證行鎖     

  因為查詢條件中有字段RUSERID,所以,為了驗證該表能否觸發行鎖,加上索引試一試。

  點擊左上角保存

  此時,索引已經加上,還是先更新第一行記錄,不提交;

  接着更新第二條記錄,並提交。 

  再來看下表數據 

  這個時候,我們再換一個查詢條件,把RUSERID去掉(就是查詢條件沒有涉及到索引列)。

  此時,我們還是先更新第一行記錄,不提交;再更新第二條記錄(提不提交無所謂,都會失敗)。

 

  這時,就證明了上面的觀點的后半句:

  如果where條件有索引條件項(字段加的有索引),觸發的將是表索引。 

  還有一種情況是:聯合索引。

  為上面的查詢條件添加聯合索引

  再次按照上面的方式和查詢條件,執行結果如下:

  如此說來,聯合索引並不能觸發行鎖,也只能觸發表鎖。

4.總結

  在mysql中,如果存儲引擎是InnoDB,結論如下: 

  第一,select.. for update, insert,update,delete操作都會觸發鎖,只要涉及到表的改動,都會觸發鎖;

  第二,表中有索引,並不代表觸發的鎖就是行鎖;

  當where條件中含有至少一個字段添加了索引,才會觸發行鎖,否則就是表鎖;

  除了上面的條件,還有兩種特殊情況:

  當表中只有聯合索引,而且是根據查詢條件所創建的索引(總之,就是他倆涉及的列一模一樣),觸發的將是表鎖,而不是行鎖;

  當查詢結果過多(具體超過全表記錄的百分之多少沒記錄),索引將會失效,觸發全表掃描,此時,也會觸發表鎖。

  第三,行鎖並不一定就是只鎖了一行,具體視情況而定。

  2020-12-09

  第四,經過測試,當where條件中攜帶表主鍵時,即使不走顯式索引(mysql是不是默認會給主鍵加索引不清楚),觸發的是行鎖,而不是表鎖。

  2020-12-14

  第五,經過測試,當執行插入語句insert into時,同樣的,當插入的字段含有索引字段時,觸發的是行鎖;否則,觸發的是表鎖。

  所以,在高並發需要頻繁插入的時候,我們不僅可以使用批量插入語句,還可以創建索引來避免鎖表。

寫在最后

  哪位大佬如若發現文章存在紕漏之處或需要補充更多內容,歡迎留言!!!

 相關推薦:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM