mysql數(shù)據(jù)庫(kù)在innodb引擎下會(huì)出現(xiàn)表鎖定和行鎖定并存情況,下面我們來(lái)分析一下這種場(chǎng)景下數(shù)據(jù)庫(kù)的加鎖機(jī)制和處理方式。
1、在MyISAM 引擎中只有表鎖,
LOCK TABLE my_tabl_name READ;? 用讀鎖鎖表,會(huì)阻塞其他事務(wù)修改表數(shù)據(jù)。
LOCK TABLE my_table_name WRITe; 用寫(xiě)鎖鎖表,會(huì)阻塞其他事務(wù)讀和寫(xiě)。
默認(rèn)情況下讀請(qǐng)求會(huì)加讀鎖,寫(xiě)請(qǐng)求寫(xiě)鎖,并且是鎖定整個(gè)表,因此大量讀的業(yè)務(wù)這種引擎效率很高。
2、在Innodb引擎又支持行鎖,行鎖分為共享鎖,一個(gè)事務(wù)對(duì)一行的共享只讀鎖。排它鎖,一個(gè)事務(wù)對(duì)一行的排他讀寫(xiě)鎖。
3、這兩中鎖定類(lèi)型的鎖共存的問(wèn)題
考慮這個(gè)例子:
事務(wù)A鎖住了表中的一行,讓這一行只能讀,不能寫(xiě)。
之后,事務(wù)B申請(qǐng)整個(gè)表的寫(xiě)鎖。
如果事務(wù)B申請(qǐng)成功,那么理論上它就能修改表中的任意一行,這與A持有的行鎖是沖突的。
數(shù)據(jù)庫(kù)需要避免這種沖突,就是說(shuō)要讓B的申請(qǐng)被阻塞,直到A釋放了行鎖。
數(shù)據(jù)庫(kù)要怎么判斷這個(gè)沖突呢?
step1:判斷表是否已被其他事務(wù)用表鎖鎖表
step2:判斷表中的每一行是否已被行鎖鎖住。
注意step2中通過(guò)遍歷查詢,這樣的判斷方法效率實(shí)在不高,因?yàn)樾枰闅v整個(gè)表。
于是就有了意向鎖。
在意向鎖存在的情況下,事務(wù)A必須先申請(qǐng)表的意向共享鎖,成功后再申請(qǐng)一行的行鎖。
在意向鎖存在的情況下,上面的判斷可以改成
step1:不變
step2:發(fā)現(xiàn)表上有意向共享鎖,說(shuō)明表中有些行被共享行鎖鎖住了,因此,事務(wù)B申請(qǐng)表的寫(xiě)鎖會(huì)被阻塞。
最終結(jié)論:
(1)申請(qǐng)意向鎖的動(dòng)作是數(shù)據(jù)庫(kù)完成的,就是說(shuō),事務(wù)A申請(qǐng)一行的行鎖的時(shí)候,數(shù)據(jù)庫(kù)會(huì)自動(dòng)先開(kāi)始申請(qǐng)表的意向鎖,不需要我們程序員使用代碼來(lái)申請(qǐng)。
(2)IX,IS是表級(jí)鎖,不會(huì)和行級(jí)的X,S鎖發(fā)生沖突。只會(huì)和表級(jí)的X,S發(fā)生沖突
行級(jí)別的X和S按照普通的共享、排他規(guī)則即可。所以之前的示例中第2步不會(huì)沖突,只要寫(xiě)操作不是同一行,就不會(huì)發(fā)生沖突。
備注:? IX? 意向排它鎖,IS 意向讀鎖,X 排它鎖,S 共享鎖