前言
sql事務的執行,如果需要鎖定數據進行更新操作,則必定離不開鎖
- 共享鎖和排他鎖
- 表鎖
- 行鎖 Record Lock
- 間隙鎖 Gap Lock
- 行鎖+間隙鎖 Next-Key Lock
- 加鎖場景(加鎖sql)
關注公眾號,一起交流,微信搜一搜: 潛行前行
1 共享鎖和排他鎖
- 排他鎖(X鎖),當前事務給記錄上鎖后(insert update delete),可以進行讀寫,其他事務不可以加任何鎖
- 共享鎖(S鎖),是指當前事務給一條記錄上鎖后,其他事務也可以給當前記錄加共享鎖。共享鎖只用於鎖定讀,如需要更新數據,是不允許的
2 表鎖
針對數據庫表的鎖,又稱為表
- 開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖沖突的概率最高,並發度最低
- MySQL表級鎖有兩種模式:表共享鎖(Table Read Lock)和表獨占寫鎖(Table Write Lock)
- myisam,memory,merge 存儲引擎只支持表鎖
表級別的 AUTO_INC 鎖
在為表某列添加 AUTO_INCREDMENT 屬性,之后插入數據時可以不指定該字段,系統會自動為它賦值,此時獲取自增值是需要 AUTO_INC 鎖鎖定的
3 行鎖 Record Lock
- innodb 既支持表鎖也支持行鎖,行鎖是針對一行記錄的鎖
- 行鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的概率最低,並發度也最高
- innodb 執行 select update delete insert 語句是不會為表加 S 鎖和 X 鎖,因為表鎖力度大,容易阻塞
- 單條索引記錄上加鎖,record lock鎖住的永遠是索引,而非記錄本身,即使該表上沒有任何索引,那么innodb會在后台創建一個隱藏的聚集主鍵索引,那么鎖住的就是這個隱藏的聚集主鍵索引。所以說當一條sql沒有走任何索引時,那么將會在每一條聚集索引后面加X鎖
何為意向鎖
如果存在行鎖的情況,想給表加鎖,怎么辦?遍歷查看表有沒有行鎖,太浪費時間了。此時意向鎖登場啦
- 意向共享鎖(IS鎖):當事務給某行記錄增加 S 鎖時,同時給表加個 IS 鎖
- 意向獨占鎖(IX鎖):當事務給某行記錄增加 X 鎖時,同時給表加個 IX 鎖
- 有了意向鎖,則不需要遍歷數據也可以直接判斷是否可以給表加鎖
4 間隙鎖 Gap Lock
mysql 在 repeatable read 隔離級別解決幻讀的,有兩種實現方式。一是靠 MVCC 方案解決;二是加鎖方案解決。然而在事務加鎖時,記錄是不存在的,是無法加行鎖的。則需要靠間隙鎖(gap lock)實現
- 例如給 id=10 記錄加 gap 鎖,鎖住(5,10)區間。另一事務想插入 id=8 的記錄,會先定位到 id=10 的記錄,然后發現存在一個 gap 鎖,則阻塞直到 第一個事務將 gap 鎖釋放掉,才可以在(5,10)區間插入記錄
- gap lock 僅僅是為了防止插入幻影記錄,並不會限制其他事務對記錄繼續加行鎖 或者 gap 鎖
5 行鎖+間隙鎖 Next-Key Lock
- next-key鎖的本質是 record lock 加一個gap lock的結合體。它既能保護該記錄,又能阻止別的事務將新的記錄插入被保護記錄的前面間隙中
6 加鎖場景(repeatable read 隔離級別加鎖 sql,忽略二級索引的加鎖操作)
- 快照讀:讀的是數據庫記錄的快照版本,sql 執行前和當前事務ID生成的最新數據
- 當前讀:讀取已提交事務生成的數據,大於當前事務ID的已提交事務,其生成的數據也可以讀取
select from
- 不加任何鎖,快照讀
select for update
- 聚簇索引上加 X 鎖,當前讀
select lock in share mode
- 聚簇索引上加行級 S 鎖,采用當前讀
insert、update 和 delete 語句的加鎖情況
- insert 在可重復讀級別加的是 next-key lock
- delete、update 是在聚簇索引記錄加上 X 鎖
歡迎指正文中錯誤
參考文章
- mysql是怎樣運行的(書籍)