Record lock單條索引記錄上加鎖,record lock鎖住的永遠是索引,而非記錄本身,即使該表上沒有任何索引,那么innodb會在后臺創建一個隱藏的聚集主鍵索引,那么鎖住的就是這個隱藏的聚集主鍵索引。所以說當一條sql沒有走任何索引時,那么將會在每一條聚集索引后面加X鎖,這個類似于表鎖,但原理上和表鎖應該是完全不同的。
Gap lock在索引記錄之間的間隙中加鎖,或者是在某一條索引記錄之前或者之后加鎖,并不包括該索引記錄本身。gap lock的機制主要是解決可重復讀模式下的幻讀問題,關于幻讀的演示和gap鎖如何解決了幻讀。關于這一塊,先給出幾個定義
快照讀:
簡單的select操作,沒有lock in share mode或for update,快照讀不會加任何的鎖,而且由于mysql的一致性非鎖定讀的機制存在,任何快照讀也不會被阻塞。但是如果事務的隔離級別是SERIALIZABLE的話,那么快照讀也會被加上共享的next-key鎖,本文不對SERIALIZABLE隔離級別做敘述。
當前讀:
官方文檔的術語叫locking read,也就是insert,update,delete,select..in share mode和select..for update,當前讀會在所有掃描到的索引記錄上加鎖,不管它后面的where條件到底有沒有命中對應的行記錄。當前讀可能會引起死鎖。
意向鎖:
innodb的意向鎖主要用戶多粒度的鎖并存的情況。比如事務A要在一個表上加S鎖,如果表中的一行已被事務B加了X鎖,那么該鎖的申請也應被阻塞。如果表中的數據很多,逐行檢查鎖標志的開銷將很大,系統的性能將會受到影響。為了解決這個問題,可以在表級上引入新的鎖類型來表示其所屬行的加鎖情況,這就引出了“意向鎖”的概念。舉個例子,如果表中記錄1億,事務A把其中有幾條記錄上了行鎖了,這時事務B需要給這個表加表級鎖,如果沒有意向鎖的話,那就要去表中查找這一億條記錄是否上鎖了。如果存在意向鎖,那么假如事務A在更新一條記錄之前,先加意向鎖,再加X鎖,事務B先檢查該表上是否存在意向鎖,存在的意向鎖是否與自己準備加的鎖沖突,如果有沖突,則等待直到事務A釋放,而無須逐條記錄去檢測。事務B更新表時,其實無須知道到底哪一行被鎖了,它只要知道反正有一行被鎖了就行了。
說白了意向鎖的主要作用是處理行鎖和表鎖之間的矛盾,能夠顯示“某個事務正在某一行上持有了鎖,或者準備去持有鎖”
不可重復讀:
指的是在同一個事務中,連續幾次快照讀,讀取的記錄應該是一樣的
不可重復讀的演示較為簡單,本文不做討論。
幻讀:
指的是在一個事務A中執行了一個當前讀操作,而另外一個事務B在事務A的影響區間內insert了一條記錄,這時事務A再執行一個當前讀操作時,出現了幻行。這和不可重復讀的主要區別就在與事務A中一個是快照讀,一個當前讀;并且事務B中一個是任何的dml操作,一個只是insert。比如在A中select * from test where id<10 lock in share mode結果集為(1,2,3),這時在B中對test表插入了一條記錄4,這時在A中重新查詢結果集就是(1,2,3,4),和事務A在第一次查詢出來的結果集不一致,這里的4就是幻行。
新聞熱點
疑難解答