您好,登錄后才能下訂單哦!
寫在前面
數據庫本質上是一種共享資源,因此在最大程度提供并發訪問性能的同時,仍需要確保每個用戶能以一致的方式讀取和修改數據。鎖機制(Locking)就是解決這類問題的最好武器。
首先新建表 test,其中 id 為主鍵,name 為輔助索引,address 為唯一索引。
CREATE TABLE `test` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` int(11) NOT NULL, `address` int(11) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idex_unique` (`address`), KEY `idx_index` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4;
INSERT 方法中的行鎖
可見,如果兩個事務先后對主鍵相同的行記錄執行 INSERT 操作,因為事務 A 先拿到了行鎖,事務 B 只能等待直到事務 A 提交后行鎖被釋放。同理,如果針對唯一索引字段 address 進行插入操作,也需要獲取行鎖,圖同主鍵插入過程類似,不再重復。
但是,如果兩個事務都針對輔助索引字段 name 進行插入,不需要等待獲取鎖,因為輔助索引字段即使值相同,在數據庫中也是操作不同的記錄行,不會沖突。
Update 方法與 Insert 方法結果類似。
SELECT FOR UPDATE 下的表鎖與行鎖
事務 A SELECT FOR UPDATE 語句會拿到表 test 的 Table Lock,此時事務 B 去執行插入操作會阻塞,直到事務 A 提交釋放表鎖后,事務 B 才能獲取對應的行鎖執行插入操作。
但是如果事務 A 的 SELECT FOR UPDATE 語句緊跟 WHERE id = 1 的話,那么這條語句只會獲取行鎖,不會是表鎖,此時不阻塞事務 B 對于其他主鍵的修改操作
輔助索引下的間隙鎖
先看下 test 表下的數據情況:
mysql> select * from test; +----+------+---------+ | id | name | address | +----+------+---------+ | 3 | 1 | 3 | | 6 | 1 | 2 | | 7 | 2 | 4 | | 8 | 10 | 5 | +----+------+---------+ 4 rows in set (0.00 sec)
間隙鎖可以說是行鎖的一種,不同的是它鎖住的是一個范圍內的記錄,作用是避免幻讀,即區間數據條目的突然增減。解決辦法主要是:
InnoDB 自動使用間隙鎖的條件為:
當 InnoDB 掃描索引記錄的時候,會首先對選中的索引行記錄加上行鎖,再對索引記錄兩邊的間隙(向左掃描掃到第一個比給定參數小的值, 向右掃描掃描到第一個比給定參數大的值, 以此構建一個區間)加上間隙鎖。如果一個間隙被事務 A 加了鎖,事務 B 是不能在這個間隙插入記錄的。
我們這里所說的 “間隙鎖” 其實不是 GAP LOCK,而是 RECORD LOCK + GAP LOCK,InnoDB 中稱之為 NEXT_KEY LOCK
下面看個例子,我們建表時指定 name 列為輔助索引,目前這列的取值有 [1,2,10]。間隙范圍有 (-∞, 1]、[1,1]、[1,2]、[2,10]、[10, +∞)
Round 1:
Round 2:
Round 3:
InnoDB 鎖機制總結
參考資料
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。