欧美一区二区三区,国内熟女精品熟女A片视频小说,日本av网,小鲜肉男男GAY做受XXX网站

Java中事務開啟是不是就是mysql加鎖了?

林國瑞2年前11瀏覽0評論

加鎖情況與死鎖原因分析

為方便大家復現,完整表結構和數據如下:

CREATETABLE`t3`(`c1`int(11)NOTNULLAUTO_INCREMENT,`c2`int(11)DEFAULTNULL,PRIMARYKEY(`c1`),UNIQUEKEY`c2`(`c2`))ENGINE=InnoDBinsertintot3values(1,1),(15,15),(20,20);

在session1執行commit的瞬間,我們會看到session2、session3的其中一個報死鎖。這個死鎖是這樣產生的:

  • 1.session1執行delete會在唯一索引c2的c2=15這一記錄上加Xlock(也就是在MySQL內部觀測到的:XLockbutnotgap);
  • 2.session2和session3在執行insert的時候,由于唯一約束檢測發生唯一沖突,會加SNext-KeyLock,即對(1,15]這個區間加鎖包括間隙,并且被seesion1的XLock阻塞,進入等待;
  • 3.session1在執行commit后,會釋放XLock,session2和session3都獲得SNext-KeyLock;
  • 4.session2和session3繼續執行插入操作,這個時候INSERTINTENTIONLOCK(插入意向鎖)出現了,并且由于插入意向鎖會被gap鎖阻塞,所以session2和session3互相等待,造成死鎖。
  • 死鎖日志如下:INSERTINTENTIONLOCK在之前的死鎖分析第四點,如果不分析插入意向鎖,也是會造成死鎖的,因為插入最終還是要對記錄加XLock的,session2和session3還是會互相阻塞互相等待。但是插入意向鎖是客觀存在的,我們可以在官方手冊中查到,不可忽略:
  • Priortoinsertingtherow,atypeofgaplockcalledaninsertintentiongaplockisset.Thislocksignalstheintenttoinsertinsuchawaythatmultipletransactionsinsertingintothesameindexgapneednotwaitforeachotheriftheyarenotinsertingatthesamepositionwithinthegap.
  • 插入意向鎖其實是一種特殊的gaplock,但是它不會阻塞其他鎖。假設存在值為4和7的索引記錄,嘗試插入值5和6的兩個事務在獲取插入行上的排它鎖之前使用插入意向鎖鎖定間隙,即在(4,7)上加gaplock,但是這兩個事務不會互相沖突等待。當插入一條記錄時,會去檢查當前插入位置的下一條記錄上是否存在鎖對象,如果下一條記錄上存在鎖對象,就需要判斷該鎖對象是否鎖住了gap。如果gap被鎖住了,則插入意向鎖與之沖突,進入等待狀態(插入意向鎖之間并不互斥)。總結一下這把鎖的屬性:
  • 1.它不會阻塞其他任何鎖;
  • 2.它本身僅會被gaplock阻塞。
  • 在學習MySQL過程中,一般只有在它被阻塞的時候才能觀察到,所以這也是它常常被忽略的原因吧...GAPLOCK在此例中,另外一個重要的點就是gaplock,通常情況下我們說到gaplock都只會聯想到REPEATABLE-READ隔離級別利用其解決幻讀。但實際上在READ-COMMITTED隔離級別,也會存在gaplock,只發生在:唯一約束檢查到有唯一沖突的時候,會加SNext-keyLock,即對記錄以及與和上一條記錄之間的間隙加共享鎖。通過下面這個例子就能驗證:這里session1插入數據遇到唯一沖突,雖然報錯,但是對(15,20]加的SNext-KeyLock并不會馬上釋放,所以session2被阻塞。另外一種情況就是本文開始的例子,當session2插入遇到唯一沖突但是因為被XLock阻塞,并不會立刻報錯“Duplicatekey”,但是依然要等待獲取SNext-KeyLock。有個困惑很久的疑問:出現唯一沖突需要加SNext-KeyLock是事實,但是加鎖的意義是什么?還是說是通過SNext-KeyLock來實現的唯一約束檢查,但是這樣意味著在插入沒有遇到唯一沖突的時候,這個鎖會立刻釋放,這不符合二階段鎖原則。這點希望能與大家一起討論得到好的解釋。如果是在REPEATABLE-READ,除以上所說的唯一約束沖突外,gaplock的存在是這樣的:普通索引(非唯一索引)的S/XLock,都帶gap屬性,會鎖住記錄以及前1條記錄到后1條記錄的左閉右開區間,比如有[4,6,8]記錄,delete6,則會鎖住[4,8)整個區間。對于gaplock,相信DBA們的心情是一樣一樣的,所以我的建議是:
  • 1.在絕大部分的業務場景下,都可以把MySQL的隔離界別設置為READ-COMMITTED;
  • 2.在業務方便控制字段值唯一的情況下,盡量減少表中唯一索引的數量。
  • 鎖沖突矩陣前面我們說的GAPLOCK其實是鎖的屬性,另外我們知道InnoDB常規鎖模式有:S和X,即共享鎖和排他鎖。鎖模式和鎖屬性是可以隨意組合的,組合之后的沖突矩陣如下,這對我們分析死鎖很有幫助。