1. 程式人生 > >【 58沈劍 架構師之路】InnoDB七種鎖——自增鎖(Auto-inc Locks)

【 58沈劍 架構師之路】InnoDB七種鎖——自增鎖(Auto-inc Locks)

一,案例說明

MySQL,InnoDB,預設的隔離級別(RR),假設有資料表:

t(id AUTO_INCREMENT, name);

 

資料表中有資料:

1, shenjian

2, zhangsan

3, lisi

 

事務A執行,還未提交

insert into t(name) values(xxx);

 

事務B執行:

insert into t(name) values(ooo);

 

問:事務B會不會被阻塞?

 

二,案例分析

InnoDB在RR隔離級別下,能解決幻讀問題,上面這個案例中:

(1)事務A先執行insert,會得到一條(4, xxx)的記錄,由於是自增列,故不用顯示指定id為4,InnoDB會自動增長,注意此時事務並未提交;

 

(2)事務B後執行insert,假設不會被阻塞,那會得到一條(5, ooo)的記錄;

 

此時,並未有什麼不妥,但如果

(3)事務A繼續insert

insert into t(name) values(xxoo);

會得到一條(6, xxoo)的記錄。

 

(4)事務A再select:

select * from t where id>3;

 

得到的結果是:

4, xxx

6, xxoo

畫外音:不可能查詢到5的記錄,再RR的隔離級別下,不可能讀取到還未提交事務生成的資料。

 

咦,這對於事務A來說,就很奇怪了,對於AUTO_INCREMENT的列,連續插入了兩條記錄一條是4,接下來一條變成了6,就像莫名其妙的幻影。

 

三,自增鎖(Auto-inc Locks)

自增鎖是一種特殊的表級別鎖(table-level lock),專門針對事務插入AUTO_INCREMENT型別的列。最簡單的情況,如果一個事務正在往表中插入記錄,所有其他事務的插入必須等待,以便第一個事務插入的行,是連續的主鍵值。

畫外音:官網是這麼說的

An AUTO-INC lock is a special table-level lock taken by transactions inserting into tables with AUTO_INCREMENT columns. In the simplest case, if one transaction is inserting values into the table, any other transactions must wait to do their own inserts into that table, so that rows inserted by the first transaction receive consecutive primary key values.

 

與此同時,InnoDB提供了innodb_autoinc_lock_mode配置,可以調節與改變該鎖的模式與行為。

 

四,假如不是自增列

上面的案例,假設不是自增列,又會是什麼樣的情形呢?

t(id unique PK, name);

 

資料表中有資料:

10, shenjian

20, zhangsan

30, lisi

 

事務A執行,在10與20兩條記錄中插入了一行,還未提交

insert into t values(11, xxx);

 

事務B執行,也在10與20兩條記錄中插入了一行:

insert into t values(12, ooo);

 

這裡,便不再使用自增鎖,那:

(1)會使用什麼鎖?

(2)事務B會不會被阻塞呢?