1. 程式人生 > >mysql高階之鎖(2)

mysql高階之鎖(2)

表鎖:

可以看我上篇部落格:https://blog.csdn.net/tuesdayma/article/details/81901679

行鎖

概述: 行鎖主要正針對於innodb(mysql5.5之後預設儲存引擎)的儲存引擎而言的,每次對資料庫操作都會進行行鎖。

特點:

1、開銷大,加鎖慢,會出現死鎖;發生鎖衝突的概率低,併發度很高。

2、會產生間隙鎖,從而導致程式無法插入問題。

3、無索引或者索引失效的記錄會變成表鎖。

4、個人覺得,行鎖沒有讀寫鎖之分,至少測出來沒有。

優化建議:

1、儘可能所有的查詢條件都使用索引,避免從行鎖變成了表鎖。

2、儘量縮小更新範圍,避免出現間隙鎖。

3、合理設計索引,避免出現表鎖。

演示

結論1:其他session沒法讀取其他session中未提交的事務(mysql預設事務級別是可重複讀,不會出現髒讀)
這裡寫圖片描述
結論2:當前session更新之後不提交的話(即行鎖不釋放的話),其他session是無法進行更新操作的。
這裡寫圖片描述
補充1:上圖也可以看到,其實第二個session執行update操作已經超時了,那麼當前session提交事務之後能不能執行第二個session的update操作呢,顯然是不行了。。。
這裡寫圖片描述
補充2:如果當前session提交的延遲較小,其他session的update操作還是能進行的。這裡有個Lock wait timeout的概念。
這裡寫圖片描述

結論3:索引失效或者無索引的話,行鎖將變成表鎖。(我們增加一個deptno這個varchar型別的欄位,然後減傷索引)

alter table test03 add deptno varchar (3)  default '111';
create index index_deptno on test03(deptno);

這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述

間隙鎖:當我們where條件是一個範圍,而這個範圍中並不存在的記錄,innodb也會對其進行加鎖,這就是間隙鎖(Next-Key鎖),這些不存在的記錄成為間隙(GAP)。
這裡寫圖片描述
分析:當session1執行所有deptno修改的時候,age=2的那條記錄雖然不在,但是也上了鎖,這就是間隙鎖,這時候如果其他session對間隙鎖中的記錄進行編輯的話,是會進入阻塞狀態的,直到session1提交事務或者超時。如果未超時還是能正常執行的,但是結果中的deptno是不會變了的,新增是能成功的!

危害:當鎖定一個範圍之後,即使不存在的記錄也不會被鎖定,從而導致其他session無法進行插入範圍之內不存在的記錄。

如何手動鎖定一行:
這裡寫圖片描述
釋放行鎖: 在沒有超時的前提下,其他session的update操作執行了。
這裡寫圖片描述
結論4: 行鎖是針對編輯操作的,對查詢操作是不起作用的。
這裡寫圖片描述
分析行鎖:show status like 'innodb_row_lock%';
這裡寫圖片描述
Innodb_row_lock_current_waits:當前正在等待的鎖

Innodb_row_lock_time:從系統啟動到現在鎖定總時間長度

Innodb_row_lock_time_avg:每次等待所花平均時間

Innodb_row_lock_time_max:從系統啟動到現在,等待最長一次所花的時間

Innodb_row_lock_waits:系統啟動到現在總共等待的次數