資料庫行鎖 表鎖 記錄鎖 間隙鎖 臨鍵鎖

2021-10-14 14:08:21 字數 1598 閱讀 1831

行鎖就是一次鎖一行或者多行記錄,mysql的行鎖是基於索引載入的,所以行鎖是要加在索引響應的行上,即命中索引。

// 假設**table的b列為索引字段,則以下更新語句只會鎖b='b'的行

update table set a = 'a' where b = 'b'

行鎖的特徵:鎖衝突概率低,併發性高,但是會有死鎖的情況出現。

表鎖就是一次鎖一整張表的記錄,在表被鎖定期間,其他事務不能對該錶進行操作,必須等當前表的鎖被釋放後才能進行操作。表鎖響應的是非索引字段,即全表掃瞄。

// 假設**table的c列為非索引字段,則以下更新語句會鎖table整張表

update table set a = 'a' where c = 'c'

表鎖的特徵:由於表鎖每次都是鎖一整張表,所以表鎖的鎖衝突機率特別高,表鎖不會出現死鎖的情況。

記錄鎖鎖的是表中的某一條記錄,記錄鎖的出現條件必須是精準命中索引並且索引是唯一索引,如主鍵id

// 以下語句,id為唯一索引

update table set a = 'a' where id = 1

間隙鎖又稱之為區間鎖,每次鎖定都是鎖定乙個區間,隸屬行鎖。既然間隙鎖隸屬行鎖,那麼,間隙鎖的觸發條件必然是命中索引的,當我們查詢資料用範圍查詢而不是相等條件查詢時,查詢條件命中索引,並且沒有查詢到符合條件的記錄,此時就會將查詢條件中的範圍資料進行鎖定(即使是範圍庫中不存在的資料也會被鎖定)

間隙鎖只會出現在可重複讀的事務隔離級別中,mysql5.7預設就是可重複讀

// id=1和id=3的行都是在資料庫中存在的

update table set a = 'a' where id > 1 and id < 3

上述**中,所鎖定的區間就是 (1,3]這個區間,不包含1,但是包含3,並且不包含4,也就是說這裡是乙個左開右閉的區間。

mysql的行鎖預設就是使用的臨鍵鎖,臨鍵鎖是由記錄鎖和間隙鎖共同實現的,上面我們學習間隙鎖時,間隙鎖的觸發條件是命中索引,範圍查詢沒有匹配到相關記錄。而臨鍵鎖恰好相反,臨鍵鎖的觸發條件也是查詢條件命中索引,不過,臨鍵鎖有匹配到資料庫記錄

例子:假如資料庫中只有三條資料1、5、7,當修改範圍為1~8時,則鎖定的區間為(1,+∞),鎖定的不單是查詢範圍,並且還鎖定了當前範圍的下乙個範圍區間,此時,查詢的區間8,在資料庫中是乙個不存在的記錄值,並且,如果此時的查詢條件是小於或等於8,也是一樣的鎖定8到後面的區間。

為什麼臨鍵鎖後匹配會這樣呢?mysql的索引是基於b+樹實現的,每個樹節點上都有多個元素,即關鍵字數,當我們的索引樹上只有1、5、7時,我們查詢1~8,這個時候由於樹節點關鍵字中並沒有8,所以就把8到正無窮的區間範圍都給鎖定了。

那麼,如果我們資料庫中id有1、5、7、10,此時我們再模糊匹配id為1~8的時候,由於關鍵字中並沒有8,所以找比8大的,也就找到了10,根據左開右閉原則,此時10也是被鎖定的,但是id為11的記錄還是可以正常進行插入的。我們的鎖都是基於索引的,而mysql中索引的底層是使用的b+樹,我們了解了b+樹的特性後,就更容易理解很多遇到鎖的問題了。

參考:

mysql 臨鍵鎖 記錄鎖 間隙鎖 臨鍵鎖

這三種並不是鎖,而是鎖的演算法。它們的共同特點是互斥的。間隙鎖和臨鍵鎖只有在rr級別中才能生效。set global transaction isolation level repeatable read select global.tx isolation 間隙鎖的目的是為了防止多個事務把記錄插入...

MySQL 表鎖 行鎖 間隙鎖

表鎖 表鎖有兩種模式 表共享讀鎖 表獨佔寫鎖 表共享讀鎖 讀鎖不會阻塞其他程序對同一表的讀操作,但阻塞寫操作,只有釋放鎖後其他程序才可以寫 表獨佔寫鎖 寫鎖會阻塞其他程序對同一表的讀和寫,只有寫鎖釋放後,其他程序才可以讀寫 簡而言之 讀鎖會阻塞寫,不阻塞讀 寫鎖阻塞讀和寫。行鎖 只鎖住某一行或多行的...

mysql行鎖和表鎖 關於資料庫行鎖與表鎖的認識

mysql mysql innodb儲存引擎 預設是自動提交事務的,所以這個測試,需要先將mysql的autocommit設定為0,關閉自動提交,需要自己手動提交事務 關閉自動提交 set autocommit 0 開啟事務 begin 這裡我主要針對的是悲觀鎖,其實也就是行鎖和表鎖,sql 加上 ...