MySQL在默認事務下各SQL語句使用的鎖分析


 數據庫使用鎖是為了支持更好的並發,提供數據的完整性和一致性。InnoDB是一個支持行鎖的存儲引擎,鎖的類型有:共享鎖(S)、排他鎖(X)、意向共享(IS)、意向排他(IX)。為了提供更好的並發,InnoDB提供了非鎖定讀:不需要等待訪問行上的鎖釋放,讀取行的一個快照。該方法是通過InnoDB的一個特性:MVCC來實現的

InnoDB有三種行鎖的算法:

1,Record Lock:單個行記錄上的鎖。

2,Gap Lock:間隙鎖,鎖定一個范圍,但不包括記錄本身。GAP鎖的目的,是為了防止同一事務的兩次當前讀,出現幻讀的情況。

3,Next-Key Lock:1+2,鎖定一個范圍,並且鎖定記錄本身。對於行的查詢,都是采用該方法,主要目的是解決幻讀的問題。

如果采用MySQL默認的事務隔離級別(可以重復讀:repeatable read

可重復讀取(Repeatable Read):防止(避免)不可重復讀取和臟讀,但是有時可能出現幻讀數據。這可以通過“共享讀鎖”和“排他寫鎖”實現。讀取數據的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。

  • 臟讀:一個事務還未提交,另外一個事務訪問此事務修改的數據,並使用,讀取了事務中間狀態數據。
  • 幻讀:一個事務讀取2次,得到的記錄條數不一致,由於2次讀取之間另外一個事務對數據進行了增刪。
  • 不可重復讀:一個事務讀取同一條記錄2次,得到的結果不一致,由於在2次讀取之間另外一個事務對此行數據進行了修改。

1.SELECT ... FROM

  >是一個快照讀,通過讀取數據庫的一個快照,不會加任何鎖,除非將隔離級別設置成了 SERIALIZABLE 。

2.SELECT ... FROM ... LOCK IN SHARE MODE

>在所有索引掃描范圍的索引記錄上加上共享的next key鎖;如果是唯一索引,只需要在相應記錄上加index record lock。這些被共享lock住的行無法進行update/delete。
>允許其它事務對這些記錄再加SHARE鎖
>如果沒有使用到索引,則鎖住全表(表級的排他鎖),無法進行insert/update/delete。

3.SELECT ... FROM ... FOR UPDATE

>在所有索引掃描范圍的索引記錄上加上排他的next key鎖。如果是唯一索引,只需要在相應記錄上加index record lock。
>如果沒有利用到索引將鎖住全表(表級的排他鎖),其它事務無法進行insert/update/delete操作。

4. UPDATE ... WHERE ...

>在所有索引掃描范圍的索引記錄上加上排他的next key鎖。如果是唯一索引,只需要在相應記錄上加index record lock。
>如果沒有利用到索引將鎖住全表(表級的排他鎖),其它事務無法進行其他的insert/update/delete操作。;

5. DELETE FROM ... WHERE ...

>語句在所有索引掃描范圍的索引記錄上加上排他的next key鎖。如果是唯一索引,只需要在相應記錄上加index record lock。
>如果沒有利用到索引將鎖住全表(表級的排他鎖),其它事務無法進行其它的insert/update/delete操作。

6. INSERT

>在插入的記錄上加一把排他鎖,這個鎖是一個index-record lock,並不是next-key 鎖,因此就沒有gap 鎖,他將不會阻止其他會話在該條記錄之前的gap插入記錄。

 

總結:

隔離級別越高,越能保證數據的完整性和一致性,但是對並發性能的影響也越大,魚和熊掌不可兼得啊。對於多數應用程序,可以優先考慮把數據庫系統的隔離級別設為Read Committed它能夠避免臟讀取,而且具有較好的並發性能。盡管它會導致不可重復讀、幻讀這些並發問題,在可能出現這類問題的個別場合,可以由應用程序采用悲觀鎖或樂觀鎖來控制。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM