MySQL 索引與鎖的使用

一.索引

索引主要是爲了提高查詢速度,能夠提高查詢速度的原因是將無序的數據變成有序(相對)

索引分聚集索引,非聚集索引
B+樹索引,Hash索引


聚集索引:一般主鍵索引就是聚集索引,聚集索引的葉子節點存儲表中的數據
非聚集索引:又稱二級索引,非主鍵索引都稱爲非聚集索引,非聚集索引的葉子節點存儲的是主鍵(爲什麼存儲的主鍵,而不是記錄所在地址呢,理由相當簡單,因爲記錄所在地址並不能保證一定不會變,但主鍵可以保證。)
通過非聚集索引查找數據時,要先去找葉子節點的主鍵,再通過主鍵去查找所要的數據,這個過程叫做回表
這就引出了另一種索引
覆蓋索引:從索引中直接查找結果,即要查詢的字段和索引是對應的,避免了回表

 


B+樹索引:一種平衡樹,從根節點到葉子節點一層一層的查找數據,InnoDB默認就是B+樹索引
Hash索引:對索引鍵值做hash運算,然後通過hash值查找所需的數據,很適合等值查詢
重複值比較多的話,就不適合用Hash索引了


二.鎖

數據庫鎖定機制簡單來說就是數據庫爲了保證數據的一致性而使各種共享資源在被併發訪問訪問變得有序所設計的一種規則。下圖來源於http://database.51cto.com/art/201810/585002.htm

 

 

 

 

使用方式來分類:悲觀鎖和樂觀鎖

悲觀鎖是在使用數據之前,加行鎖(使用 select * from tablename where id=2 for update手動加鎖)
樂觀鎖是一種邏輯或者說一種思想,它不是數據庫層面上的鎖,要手動添加,一般額外加一個version字段

鎖的粒度分類:表級鎖,行級鎖,頁級鎖

用的比較多的是表級鎖和行級鎖

表級鎖:開銷小,加鎖快;不會出現死鎖(因爲MyISAM會一次性獲得SQL所需的全部鎖);鎖定粒度大,發生鎖衝突的概率最高,併發度最低。

行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。

MySIAM只支持表級鎖,
InnoDB支持表級鎖和行級鎖
行鎖跟索引有關,如果某行上沒有索引,則會自動變爲表鎖


鎖的類型分類:共享鎖,排他鎖,意向共享鎖,意向排它鎖

共享鎖,排它鎖按照鎖的粒度都是行級鎖

意向共享鎖,意向排它鎖 都是表級鎖,主要是用來標記一個事務對於這張表操作的一個意向

共享鎖:一般是查詢的時候加共享鎖,其他事務可以讀,但是不能更改
排他鎖:一般是修改操作時,加排他鎖
意向共享鎖:一個事務對某張表的一行加共享鎖之前,必須加一個意向共享鎖或者更強的鎖
意向排他鎖:一個事務對某張表的一行加排他鎖之前,必須加一個意向排他鎖

 

其他的鎖還有間隙鎖,記錄鎖,臨鍵鎖

間隙鎖:鎖住的是一個索引的範圍,啓用它有一個前置條件,就是數據庫隔離級別必須是Repeatable Read(可重複讀),這也是InnoDB的默認隔離級別,假設我們將隔離級別降到Read Committed(讀提交),間隙鎖將會自動失效。

間隙鎖的使用,能夠有效的防止幻讀。

記錄鎖:鎖住一條記錄,這是Read Committed(讀提交)事務級別的默認鎖級別。記錄鎖是作用於索引的,所以,當查詢不是作用於索引上時,系統會創建一個隱式的聚集索引,然後作用在索引上。
共享記錄鎖:select * from tablename where id=1 lock in share mode
排他記錄鎖:select * from tablename where id=1 for update

臨建鎖:臨鍵鎖就是記錄鎖+間隙鎖的組合方式。這是Repeatable Read(可重複讀)隔離級別的默認鎖級別。使用臨鍵鎖有一個好處,就是,假設我們執行一個查詢
select * from tablename where id = 1;
如果id是唯一索引,那麼臨鍵鎖就會降級爲記錄鎖,鎖住這條記錄,而不是去鎖住一個範圍。

這裏引出兩個概念:

鎖等待:由於資源不足引起的排隊等待現象

死鎖:兩個或多個事務在同一資源上相互佔用,並請求鎖定對方佔用的資源,從而導致惡性循環。

一般的處理方式是將持有最少行級鎖的事務進行回滾。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章