create table test_innodb_insert_lock
(id int not null primary key auto_increment,
uk int not null unique key) engine = innodb;
開啟三個(gè)終端執(zhí)行窗口,模擬三個(gè)session
Mysql(當(dāng)前問題是在使用innodb引擎的前提下)的鎖種類很多藏否,而insert時(shí)所涉及到的鎖情況較select脉顿、update疮装、delete有所不同团滥,相對(duì)更復(fù)雜一些脏嚷。
mysql中如何保障uk的唯一性赁炎?肯定是加鎖是尖。那在哪里加鎖意系?對(duì)誰加鎖?如果要操作的數(shù)據(jù)本身還不存在饺汹,那又該如何加鎖蛔添?
mysql是索引組織表,基于B+樹(多路有序平衡查找樹)來構(gòu)建主鍵索引和二級(jí)索引。唯一索引也是二級(jí)索引迎瞧,但其唯一性夸溶,幾乎等同于主鍵索引(所以如果表中沒有主鍵只有唯一鍵,唯一鍵是代替主鍵作用的)凶硅。所以mysql加鎖是在索引記錄上加鎖缝裁。
因?yàn)閗ey由Session1創(chuàng)建,因而在該key上持有X-lock(排他鎖)足绅,而Session2和Session3內(nèi)部獲取到DuplicateKey異常后捷绑,會(huì)先獲取S-lock(共享鎖,讀取該key)氢妈,之后再嘗試升級(jí)鎖成X-lock胎食,然后如果有機(jī)會(huì)的話,執(zhí)行插入允懂。這里的機(jī)會(huì)厕怜,是指Session1回滾并釋放了X-lock。下圖是Session1執(zhí)行rollback后Session2蕾总、Session3的反應(yīng):
當(dāng)然粥航,如果session1正常commit,session2和session3會(huì)報(bào)沖突