鎖們
什么是間隙鎖奏窑?
間隙鎖(Gap Lock):鎖加在不存在的空閑空間校哎,可以是兩個(gè)索引記錄之間膨报,也可能是第一個(gè)索引記錄之前或最后一個(gè)索引之后的空間。
當(dāng)我們用范圍條件而不是相等條件索引數(shù)據(jù)即横,并請(qǐng)求共享或排他鎖時(shí),InnoDB會(huì)給符合條件的已有數(shù)據(jù)記錄的索引項(xiàng)枷鎖裆赵;對(duì)于鍵值在條件范圍內(nèi)但并不存在的記錄东囚,叫做“間隙(GAP)”。
InnoDB也會(huì)對(duì)這個(gè)“間隙”枷鎖顾瞪,這種鎖機(jī)制就是所謂的間隙鎖(Next-Key鎖)舔庶。
間隙鎖的危害
因?yàn)镼uery執(zhí)行過程中通過范圍查找的話,他會(huì)鎖定整個(gè)范圍內(nèi)所有的索引鍵值陈醒,即使這個(gè)鍵值并不存在惕橙。間隙鎖有一個(gè)比較致命的弱點(diǎn),就是當(dāng)鎖定一個(gè)范圍鍵值之后钉跷,即使某些不存在的鍵值也會(huì)被無辜的鎖定弥鹦,也造成在鎖定的時(shí)候無法插入鎖定鍵值范圍內(nèi)的任何數(shù)據(jù)。在某些場景下這可能會(huì)對(duì)性能造成很大的危害爷辙。
間隙鎖與死鎖
最近用戶反饋說系統(tǒng)老是出現(xiàn)insert時(shí)彬坏,等待超時(shí)了,最后發(fā)現(xiàn)是insert間隙鎖膝晾!間隙鎖是innodb中行鎖的一種栓始, 但是這種鎖鎖住的卻不止一行數(shù)據(jù),他鎖住的是多行血当,是一個(gè)數(shù)據(jù)范圍幻赚。間隙鎖的主要作用是為了防止出現(xiàn)幻讀,但是它會(huì)把鎖定范圍擴(kuò)大臊旭,
有時(shí)候也會(huì)給我們帶來麻煩落恼,我們就遇到了。 在數(shù)據(jù)庫參數(shù)中离熏, 控制間隙鎖的參數(shù)是:
innodb_locks_unsafe_for_binlog佳谦,
這個(gè)參數(shù)默認(rèn)值是OFF, 也就是啟用間隙鎖滋戳, 他是一個(gè)bool值钻蔑, 當(dāng)值為true時(shí)表示disable間隙鎖啥刻。
那為了防止間隙鎖是不是直接將innodb_locaks_unsafe_for_binlog設(shè)置為true就可以了呢? 不一定矢棚!
而且這個(gè)參數(shù)會(huì)影響到主從復(fù)制及災(zāi)難恢復(fù)郑什, 這個(gè)方法還尚待商量。
間隙鎖的出現(xiàn)主要集中在同一個(gè)事務(wù)中先delete后 insert的情況下蒲肋, 當(dāng)我們通過一個(gè)參數(shù)去刪除一條記錄的時(shí)候蘑拯,
如果參數(shù)在數(shù)據(jù)庫中存在,那么這個(gè)時(shí)候產(chǎn)生的是普通行鎖兜粘,鎖住這個(gè)記錄申窘, 然后刪除, 然后釋放鎖孔轴。如果這條記錄不存在剃法,
問題就來了, 數(shù)據(jù)庫會(huì)掃描索引路鹰,發(fā)現(xiàn)這個(gè)記錄不存在贷洲, 這個(gè)時(shí)候的delete語句獲取到的就是一個(gè)間隙鎖,然后數(shù)據(jù)庫會(huì)向左掃描掃到第一個(gè)比給定參數(shù)小的值晋柱,向右掃描掃描到第一個(gè)比給定參數(shù)大的值优构, 然后以此為界,構(gòu)建一個(gè)區(qū)間雁竞, 鎖住整個(gè)區(qū)間內(nèi)的數(shù)據(jù)钦椭, 一個(gè)特別容易出現(xiàn)死鎖的間隙鎖誕生了。