Innodb索引和鎖的學習筆記

附錄:前段時間學習了下innodb鎖的相關知識,對鎖和事務有了大致理解,這裏作個小總結。 mysql

1.Innodb事務和鎖的關係。

   Innodb區別於MyISAM的兩個特色就是Innodb對於事務的支持和對行鎖的支持。事務要求了一組SQL語句的ACID特性,同時爲了不對一行記錄的併發更新,innodb自己會在必定狀況下加鎖,而後等語句所在的事務退出後(rollbak或者commit)釋放鎖。其實在autocommit=true時,一個sql自己就是一個事務。 sql

   Innodb在執行Update,Delete,Insert時會對記錄加寫鎖(排他鎖,加上排他鎖後,不能再加共享鎖和排他鎖)。而Select語句不會對記錄加鎖。 數據庫

 

   共享鎖:SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。 併發

   排他鎖(X):SELECT * FROM table_name WHERE ... FOR UPDATE。 工具

 

舉例: 學習

 

 

   如圖,左側事務加了排他鎖(for update),右側事務直接查詢不會等待(不加鎖),加排他鎖失敗,加共享鎖失敗(lock in share mode)。左側事務提交或者回滾後,釋放鎖。 優化

 

2.Innodb的行鎖特性。

   Innodb使用行鎖加鎖記錄,也就是說會在加鎖條件下對訪問的具體行進行加鎖,而不會鎖住全表。這樣可以大大提升表訪問的吞吐量,減小沒必要要的記錄鎖。而Innodb的行鎖是使用索引實現的,所以有一下幾點須要注意: spa

  •     若是對已一條加鎖語句訪問的數據走不了索引或者沒加索引,其實他鎖的是全表,這點須要注意。
  •     若是索引使用的是範圍,那麼他會鎖住命中的記錄,同時會鎖住不存在的記錄間隙防止插入(這一行並不存在),gap lock。

          如圖 線程

          

    

       左邊事務鎖住了age>3的記錄,那麼很天然age=4的記錄會被鎖住。而在右邊事務中,插入一條age=5個記錄,而插入操做被hang住,這就是間隙鎖。間隙鎖是爲了不幻象讀的發生,即A事務批量update condition=x的記錄,同時B事務插入了一條condition=X的記錄,那麼A事務提交後,發現仍然存在一條沒有更新的記錄,貌似出現了幻覺,這就是幻讀。 htm

       由於間隙鎖彷佛爲了防止插入,因此update age=5並不鎖表,由於記錄並不存在- -。

  •     若是兩個查詢走不一樣索引,可是卻須要處理同一條記錄,會競爭鎖。
  •     雖然兩個查詢到的記錄不一樣,可是走的是同一個索引,那麼依然會競爭鎖。

   例如:



 
 learntransaction表在age加了索引,左邊窗口查詢age=122 AND id=6的記錄,右邊窗口查詢age=122 and id=3的記錄,能夠發現二者的記錄並不一樣,可是卻出現了鎖競爭,由於兩個公用了一個索引age=122。

  •     當where語句的查詢字段涉及到多個索引時,mysql會優化sql決定走的索引,因此若是id也加了索引,那麼索然在where語句裏age在前面,但不必定走age的索引而走了id的索引。因此這個時候對於怎麼加鎖須要看具體索引的使用狀況,建議使用explain工具查詢執行計劃判斷。

        這裏須要注意的是,慢查詢致使數據庫hang住並不必定是由於競爭鎖,慢查詢可能由於要更新的記錄太多,致使sql遲遲沒法完成,而innodb默認32個槽,也就是32個併發工做線程,當32個線程都在運行而沒法接收新的sql時,數據就可能被hang住了,而與鎖無關。

 

 

參考資料:

《深刻淺出MySQL——數據庫開發、優化與管理維護》 http://book.51cto.com/art/200803/68127.htm

相關文章
相關標籤/搜索