最近一段時間在準備新員工培訓的材料,本來打算介紹介紹概念就OK的,但是既然寫了事務的章節,就特別想介紹一下鎖,介紹了鎖,就忍不住想介紹一下Next-Key Lock。 大家知道,標準的事務隔離級別有READ UNCOMMITTED,READ COMMITTED,REPEATED READ和SERIA
最近一段時間在準備新員工培訓的材料,本來打算介紹介紹概念就OK的,但是既然寫了事務的章節,就特別想介紹一下鎖,介紹了鎖,就忍不住想介紹一下Next-Key Lock。
大家知道,標準的事務隔離級別有READ UNCOMMITTED,READ COMMITTED,REPEATED READ和SERIALIZABLE。其中InnoDB預設實現了REPEATED READ級別,這個級別可以解決非一致性讀的問題,但是不能解決幻讀的問題,不過InnoDB採用了Next Key Lock演算法,在該級別實現了幻讀保護。
至於什麼是幻讀,這個概念可以在官方文檔上找到答案,這裡就不再贅述了。
先看一個例子,按照下麵的規則建表:
CREATE TABLE `test` ( `id` int(11) DEFAULT NULL, KEY `id` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into test values (1), (3), (5), (8), (11);
註意,這裡id上是有索引的,因為該演算法總是會去鎖住索引記錄。
現在,該索引可能被鎖住的範圍如下:
(-∞, 1], (1, 3], (3, 5], (5, 8], (8, 11], (11, +∞)
此時,按照下麵表格中的順序開啟兩個Session,在Session B執行到第六步之前,都是可以成功的,第六步開始阻塞,第八步又可以正常執行。這樣,就能知道Session A中的SQL實際上鎖住了一個範圍,除了鎖住了8所在的(5, 8]區間,還同時鎖住了下一個區間:(8, 11],所以插入12就不在鎖定範圍內了。
這裡有個問題我還沒有想清楚,就是為什麼插入5還會被阻塞,如果誰知道請留言告知,謝謝,我自己也會找資料研究。
order | Session A | Session B |
1 | begin; | |
2 | select * from test where id = 8 for update; | |
3 | begin; | |
4 | insert into test select 1; | |
5 | insert into test select 4; | |
6 | insert into test select 5; | |
7 | insert into test select 9; | |
8 | insert into test select 12; |
上面這個情況是輔助索引且不唯一的情況的鎖。如果是唯一索引呢?
如果將id列修改為主鍵,上面這個表格中,Session B第四和六步主鍵衝突就不說了,其他的步驟都可以執行成功, (5, 8], (8, 11]這兩個區間內的所有值(主鍵不衝突)都可以成功插入表中。這種現象的原因是,索引唯一,InnoDB會把鎖降級成Record Lock,只會鎖住一個記錄而已,這樣能很好的提升併發性。
利用Next Key Lock,InnoDB可以在REPEATABLE READ級別下,實現幻讀保護。
參考:http://www.cnblogs.com/zhoujinyi/p/3435982.html