mysql的鎖機制詳解

這段時間一直在學習mysql數據庫。項目組一直用的是oracle,因此對mysql的瞭解也不深。本文主要是對mysql鎖的總結。html

Mysql的鎖主要分爲3大類:mysql

   表級鎖:存儲引擎爲Myisam。鎖住整個表,特色是開銷小,加鎖快,鎖定力度大,發生鎖衝突的機率最高,併發度最低。sql

   頁級鎖:存儲引擎爲BDB。鎖住某一頁的數據(16kb左右),特色:開銷和枷鎖時間介於表級和行級之間;會出現死鎖,鎖定力度介於表鎖和行鎖之間,併發度通常。數據庫

   行級鎖:存儲引擎爲innodb。鎖住某一行的數據,特色:鎖的實現更加複雜,開銷大,加鎖速度慢。安全

根據以上特色,僅從鎖的角度來講:表級鎖更適合於以查詢爲主,只有少許按索引條件更新數據的應用,如Web應用;而行級鎖則更適合於有大量按索引條件併發更新少許不一樣數據,同時又有併發查詢的應用,如一些在線事務處理(OLTP)系統。併發

 

接下來進行行級鎖的詳解,行級鎖主要分爲如下7類:共享/排他鎖、意向鎖、記錄鎖、間隙鎖、臨建鎖、插入意向鎖、自增鎖。oracle

 

共享/排他鎖:性能

  共享鎖:又稱讀鎖,能夠容許讀,但不能寫。共享鎖能夠與共享鎖一塊兒使用。語句:學習

select ... lock in share mode

 

   排他鎖:又稱寫鎖,不能容許讀,也不能容許寫,排他鎖不能與其餘所一塊兒使用。語句:優化

 

select ... for update

mysql中,updatedeleteinsertalter這些寫的操做默認都會加上排他鎖。Select默認不會加任何鎖類型。一旦寫數據的任務沒有完成,數據是不能被其餘任務讀取的,這對併發操做有較大的影響。

 

意向鎖:innoDB爲了支持多粒度的鎖,即容許行級鎖和表級鎖共存,而引入意向鎖。意向鎖是指將來的某個時刻,事務可能要加共享/排他鎖,先提早聲明一個意向。這樣若是有人嘗試對全表進行修改,就不須要判斷表中的數據是否被加鎖了,只須要經過等待意向互斥鎖被釋放就好了。

   意向共享鎖(IS):事務想要在得到表中某些記錄的共享鎖,須要在表上先加意向共享鎖。

   意向互斥鎖(IX):事務想要在得到表中某些記錄的互斥鎖,須要在表上先加意向互斥鎖。

意向鎖其實不會阻塞全表掃描以外的任何請求,它們的主要目的是爲了表示是否有人請求鎖定表中的某一行數據。

 

  記錄鎖(RS):單個行記錄上的鎖。記錄鎖老是會鎖住索引記錄,若是innoDB存儲引擎表

在創建的時候沒有設置任何一個索引,那麼innoDB存儲引擎會使用隱式的主鍵來進行鎖定。

 

間隙鎖(GR):間隙鎖鎖住記錄中的間隔,即範圍查詢的記錄。

 Select * From user where id between 1 and 10 for update

   這個腳本會鎖住110 的數據,以防止其餘事務修改該區間的記錄;

 

間隙鎖的主要目的,就是爲了防止其餘事務在間隔中插入數據,以致使「不可重複讀」。若是把事務的隔離級別降級爲讀提交(Read Committed, RC),間隙鎖則會自動失效

 

臨建鎖(next-key Locks):臨建鎖是記錄鎖和間隙鎖的組合,鎖的範圍既包含記錄又包含索引區間。默認狀況下,innoDB使用臨建鎖來鎖定記錄。但當查詢的索引含有惟一屬性的時候,臨建鎖會進行優化,將其降級爲記錄鎖,即僅鎖住索引自己,不是範圍。

臨鍵鎖的主要目的,也是爲了不幻讀(Phantom Read)。若是把事務的隔離級別降級爲RC,臨鍵鎖則也會失效。

 

 插入意向鎖(insert intention locks):對已有數據行的修改和刪除,必須加互斥鎖,對於數據的插入,加插入意向鎖。是專門針對於insert操做的。

 

自增鎖(auto-inc locks):是一種特殊的表級別的鎖,專門針對事務插入auto-increment類型的列。最簡單的狀況,若是一個事務正在往表中插入記錄,全部其餘事務的插入必須等待,以便第一個事務插入的行,是連續的主鍵值。

 

---------------------------------------------------------分界線--------------------------------------------------------------

接下看講一下其餘的鎖:

  死鎖:產生是由於線程鎖之間交替等待產生的。值兩個或兩個以上的事務在執行過程當中,因爭奪資源而形成的一種相互等待的現象。

   Mysql處理死鎖的方法:根據數據寫的數據量的大小來回滾小事務。

 

   樂觀/悲觀鎖:

      樂觀鎖:樂觀的假定大機率不會發生併發更新衝突,訪問,處理數據的過程當中不加鎖,只在更新數據時根據版本號或時間戳判斷是否有衝突,有則處理,無責提交事務。

若是系統併發量很是大,悲觀鎖會帶來很是大的性能問題,選擇使用樂觀鎖,如今大部分應用屬於樂觀鎖

     悲觀鎖:悲觀的假定大機率會發生併發更新衝突,訪問,處理數據前就加排他鎖,在整個數據處理過程當中鎖定數據,事務提交或回滾後才釋放鎖。

     優勢:

     悲觀併發控制其實是「先取鎖再訪問」的保守策略,爲數據處理的安全提供了保證。

     缺點:

    (a)在效率方面,處理加鎖的機制會讓數據庫產生額外的開銷,還有增長產生死鎖的機會;

    (b) 在只讀型事務處理中因爲不會產生衝突,也不必使用鎖,這樣作只能增長系統負載;還有會下降了並行性,一個事務若是鎖定了某行數據,其餘事務就必須等待該事務處理完才能夠處理那行數

 

建議:

  1. 控制事務的大小(操做寫的數據量)
  2. 使用鎖的時候儘可能要配合與攜帶索引的字段使用,避免升級爲表鎖
  3. 範圍查詢,儘可能減小基於範圍查詢的事務的大小
  4. 若是業務必需要使用鎖,鎖的衝突特別高的話,改成表鎖
  5. 能夠根據項目自身的狀況調節事務的innodb_flush_log_at_trx_commit

 

感謝如下博主的文檔支持:

http://www.javashuo.com/article/p-vxbgqfet-t.html

http://www.javashuo.com/article/p-rwabkszm-gz.html

http://www.javashuo.com/article/p-qfnrbqyh-gh.html

相關文章
相關標籤/搜索