MySQL / 各种锁
一、相關名詞
- 表級鎖:鎖定整個表。
- 頁級鎖:鎖定一頁。
- 行級鎖:鎖定一行。
- 間隙鎖(Next-Key):鎖定不存在記錄的間隙。
- 共享鎖:S 鎖,MyISAM 叫做讀鎖。
- 排他鎖:X 鎖,MyISAM 叫做寫鎖。
- 悲觀鎖:抽象性,不真實存在這個鎖。
- 樂觀鎖:抽象性,不真實存在這個鎖。
二、InnoDB 與 MyISAM
Mysql 在5.5之前默認使用 MyISAM 存儲引擎,之后使用 InnoDB 。查看當前存儲引擎:
show variables like '%storage_engine%';MyISAM 操作數據都是使用的表鎖,你更新一條記錄就要鎖整個表,導致性能較低,并發不高。當然同時它也不會存在死鎖問題。
而 InnoDB 與 MyISAM 的最大不同有兩點:一是 InnoDB 支持事務;二是 InnoDB 采用了行級鎖。也就是你需要修改哪行,就可以只鎖定哪行。
索引分為主鍵索引和非主鍵索引兩種,如果一條 sql 語句操作了主鍵索引,Mysql 就會鎖定這條主鍵索引;如果一條語句操作了非主鍵索引,MySQL會先鎖定該非主鍵索引,再鎖定相關的主鍵索引。
InnoDB 行鎖是通過給索引項加鎖實現的,如果沒有索引,InnoDB 會通過隱藏的聚簇索引來對記錄加鎖。也就是說:如果不通過索引條件檢索數據,那么InnoDB將對表中所有數據加鎖,實際效果跟表鎖一樣。因為沒有了索引,找到某一條記錄就得掃描全表,要掃描全表,就得鎖定表。
三、行鎖
在 Mysql 中,行級鎖并不是直接鎖記錄,而是鎖索引。InnoDB行鎖是通過給索引上的索引項加鎖來實現的,這一點MySQL與Oracle不同,后者是通過在數據塊中對相應數據行加鎖來實現的。?InnoDB 這種行鎖實現特點意味著:只有通過索引條件檢索數據,InnoDB 才使用行級鎖,否則,InnoDB 將使用表鎖!
即便在條件中使用了索引字段,但是否使用索引來檢索數據是由 MySQL 通過判斷不同執行計劃的代價來決定的,如果 MySQL 認為全表掃描效率更高,比如對一些很小的表,它就不會使用索引,這種情況下InnoDB 將使用表鎖,而不是行鎖。因此,在分析鎖沖突時,別忘了檢查 SQL 的執行計劃,以確認是否真正使用了索引。
四、間隙鎖
當我們用范圍條件而不是相等條件檢索數據,并請求共享或排他鎖時,InnoDB 會給符合條件的已有數據記錄的索引項加鎖;對于鍵值在條件范圍內但并不存在的記錄,叫做“間隙(GAP)”,InnoDB 也會對這個“間隙”加鎖,這種鎖機制就是所謂的間隙鎖(Next-Key鎖)。
舉例來說,假如 emp 表中只有 101 條記錄,其 empid 的值分別是 1、2、…、100、101,下面的 SQL:
Select * from emp where empid > 100 for update;該 SQL 是一個范圍條件的檢索,InnoDB 不僅會對符合條件的 empid 值為 101 的記錄加鎖,也會對 empid 大于 101(這些記錄并不存在)的“間隙”加鎖。
InnoDB 使用間隙鎖的目的,一方面是為了防止幻讀,以滿足相關隔離級別的要求。對于上面的例子,要是不使用間隙鎖,如果其他事務插入了 empid 大于 100 的任何記錄,那么本事務如果再次執行上述語句,就會發生幻讀。
很顯然,在使用范圍條件檢索并鎖定記錄時,InnoDB 這種加鎖機制會阻塞符合條件范圍內鍵值的并發插入,這往往會造成嚴重的鎖等待。因此,在實際應用開發中,尤其是并發插入比較多的應用,我們要盡量優化業務邏輯,盡量使用相等條件來訪問更新數據,避免使用范圍條件。
還要特別說明的是,InnoDB 除了通過范圍條件加鎖時使用間隙鎖外,如果使用相等條件請求給一個不存在的記錄加鎖,InnoDB 也會使用間隙鎖!
?
轉載于:https://blog.csdn.net/localhost01/article/details/78720727
?
(SAW:Game Over!)
總結
以上是生活随笔為你收集整理的MySQL / 各种锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C/C++ / 函数调用规则汇总
- 下一篇: linux cmake编译源码,linu