深入理解数据库行锁与表锁
當插入數據時,就鎖定表,這叫做”鎖表”;當更新數據時,就鎖定行,這叫做”鎖行”。
鎖在數據網絡傳輸中是一個非常重要的概念,當多個用戶對數據庫進行操作時,會帶來數據不一致的情況,所以,鎖主要是在多用戶情況下保證數據庫數據完整性和一致性。
當然,數據庫中的鎖遠不止于上面提到的兩種。通常提及數據庫鎖,想必大家優先想到的,必然是樂觀鎖,數據庫樂觀鎖可以幫助我們解決很多問題,但數據庫中還有很多其它的鎖,總結一下大概有如下:悲觀鎖、樂觀鎖、表鎖、行鎖、臨間鎖、間隙鎖、記錄鎖、共享鎖、排他鎖、意向共享鎖、意向排他鎖。
Mysql中的鎖機制基本上都是采用的悲觀鎖來實現的。我們先來看一下”行鎖”。
行鎖
顧名思義,行鎖就是一鎖鎖一行或者多行記錄,mysql的行鎖是基于索引加載的,所以行鎖是要加在索引響應的行上,即命中索引。
數據庫表中有一個主鍵索引和一個普通索引,Sql語句基于索引查詢,命中兩條記錄。此時行鎖一鎖就鎖定兩條記錄,當其他事務訪問數據庫同一張表時,被鎖定的記錄不能被訪問,其他的記錄都可以訪問到。
行鎖的特征:鎖沖突概率低,并發性高,但是會有死鎖的情況出現。
表鎖
顧名思義,表鎖就是一鎖鎖一整張表,在表被鎖定期間,其他事務不能對該表進行操作,必須等當前表的鎖被釋放后才能進行操作。表鎖響應的是非索引字段,即全表掃描,全表掃描時鎖定整張表,sql語句可以通過執行計劃看出掃描了多少條記錄。
由于表鎖每次都是鎖一整張表,所以表鎖的鎖沖突幾率特別高,表鎖不會出現死鎖的情況。
當更新數據庫數據時,如果沒有觸發索引,則會鎖表,鎖表后再對表做任何變更操作都會導致鎖沖突,所以表鎖的鎖沖突概率較高。
在mysql中,行鎖又衍生了其他幾種算法鎖,分別是 記錄鎖、間隙鎖、臨鍵鎖;我們依次來看看這三種鎖,什么是記錄鎖呢?
記錄鎖
我們找到行鎖是命中索引,一鎖鎖的是一張表的一條記錄或者是多條記錄,記錄鎖是在行鎖上衍生的鎖,我們來看看你記錄鎖的特征:
記錄鎖:記錄鎖鎖的是表中的某一條記錄,記錄鎖的出現條件必須是精準命中索引并且索引是唯一索引,如主鍵id,就像我們上面描述行鎖時使用的sql語句圖,在這里就挺適用的。
圖中id是唯一索引,此時鎖的就是一條記錄,命中索引為唯一索引,此時使用的鎖就是記錄鎖了。相信學習完行鎖后,再學習記錄鎖就簡單很多了吧。
間隙鎖
間隙鎖又稱之為區間鎖,每次鎖定都是鎖定一個區間,隸屬行鎖。既然間隙鎖隸屬行鎖,那么,間隙鎖的觸發條件必然是命中索引的,當我們查詢數據用范圍查詢而不是相等條件查詢時,查詢條件命中索引,并且沒有查詢到符合條件的記錄,此時就會將查詢條件中的范圍數據進行鎖定(即使是范圍庫中不存在的數據也會被鎖定),我們通過代碼演示一下:
間隙鎖只會出現在可重復讀的事務隔離級別中,mysql5.7默認就是可重復讀。間隙鎖鎖的是一個區間范圍,查詢命中索引但是沒有匹配到相關記錄時,鎖定的是查詢的這個區間范圍,上述代碼中,所鎖定的區間就是 (1,3]這個區間,不包含1,但是包含3,并且不包含4,也就是說這里是一個左開右閉的區間。
設置事務隔離級別為不可重復讀 set session transaction isolation level read committed; 查看當前事務級別 SELECT @@tx_isolation臨鍵鎖
mysql的行鎖默認就是使用的臨鍵鎖,臨鍵鎖是由記錄鎖和間隙鎖共同實現的,上面我們學習間隙鎖時,間隙鎖的觸發條件是命中索引,范圍查詢沒有匹配到相關記錄。而臨鍵鎖恰好相反,臨鍵鎖的觸發條件也是查詢條件命中索引,不過,臨鍵鎖有匹配到數據庫記錄;
?
總結
以上是生活随笔為你收集整理的深入理解数据库行锁与表锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis分布式锁的实现原理
- 下一篇: 数据库唯一主键如何实现幂等性?