由於書是從圖書館借來的,記下一些學習的過程,便於以後查看
1. 鎖是資料庫區別於檔案系統的重要特性之1,鎖機制用於管理對共用檔案的並發訪問
innodb使用的是行級鎖
myisam,使用的是表級鎖,在並發條件下,讀操作沒有問題,但是並發插入會有效能上的影響
sql server 2005之前的版本都是頁級鎖的,相對於myisam言,並發訪問上效能有所提高,在2005以及之後,sql server 支援開放式並行存取和封閉式並行存取,在開放式並行存取下執行行級鎖,但實現方式和與innodb不相同,在sql server中,鎖是一種稀有的資源,而在mysql innodb中,鎖沒有相關的開銷,可以同時得到並發性和一致性
2. innodb的鎖類型
共用鎖定和獨佔鎖定
共用鎖定 (S Lock): 允許事務讀一行資料
獨佔鎖定(X Lock):允許事務寫或者修改一行資料
,可以在一行上使多個S鎖,但是只要有X鎖,就不能在加其他的鎖了
innodb儲存引擎支援多粒度鎖定,這種鎖定允許在表級和行級上的鎖同時存在,為了支援在不同粒度上架鎖,innodb 提供了一種意圖鎖定,意圖鎖定是表級鎖,且分為 意圖共用鎖和排他共用鎖定
3. 一致性非鎖定讀
一致性非鎖定讀,是指innodb通過行多版本控制技術的方式來讀取資料庫中的資料,入如果讀取的資料進行中刪除或者更新,這時讀取操作不會因此等待行上的鎖釋放,而會去讀取行的一個快照(快照指的是該行之前的版本的資料,該實現通過undo段實現),而因為undo段是用來在事務中復原資料的,因此快照沒有額外的開銷,讀取快照不需要加鎖
可以看出的是,一致性非鎖定讀,大大提高了資料讀取的並發性,在innodb中,只是預設的方式,即讀取不會佔用和等待表上的鎖,但是,在事務不同的隔離等級下,讀取方式還是有所不同的,並不是每一個隔離等級下讀取都是一致性的讀。
4. 自增長和鎖
在innodb的記憶體結構中,對每一個含有自增長值的表都有一個自增長計數器,對含有自增長計數器的表進行插入時,這個計數器會被初始化,然後使用:
select max(auto_inc_col) from table for update ,插入操作接著會依據這個自增長的計數器值加1賦予自增長列,這種實現方式稱為:AUTO_INC Locking ,這種鎖實際上是一種表級鎖機制,為了提高插入的效能,鎖不是在一個事務完成後才釋放,而是在完成對自增長的值插入之後就立即釋放,鎖住的時間越短越好
但是這種方式,在大量的插入操作中還是會有效能的問題,1) 對於自增長型的列的插入效能較差,必須等待前一個插入完成後才能插入下一個(雖然不用等待事務完成),2)對於insert select 的大資料量的插入,會影響插入的效能,因為另一個事務的插入可能會被阻塞
從mysql 5.1.22起,innodb提供了一種 輕量級互斥量的自增長實現機制,便於提高並發的效能,使用一個參數 :innodb_autoinc_lock_mode,預設值為1
在innodb 中,自增長值的列必須是索引,並且是索引的第一列,如果是第2列也會報錯,另外,myisam是表級鎖,不用考慮自增長並發插入
5. 外鍵和鎖
外鍵主要用於參考完整性的檢查,在innodb中,如果沒有對外鍵列加索引,innodb會隱式的對其加索引,這樣可以避免表級鎖
對於外鍵的插入,首先要查詢父表中的記錄,即select 父表,但對父表的select,不使用一致性非鎖定讀,因為這樣會發生資料不一致性,innodb使用的是select ... lock in share mode ,主動對父表加一個S鎖,這樣,如果在父表上已經加了一個X鎖,子表的操作就會被阻塞
6. 鎖的演算法
innodb中有3種行鎖的演算法設計
1) Record lock,單個行記錄上的鎖
2)Gap Lock 間接鎖,鎖定的是一個範圍,但不包含記錄本身
3) Next-key Lock : = Record lock + Gap lock ,鎖定一個範圍,並且包含記錄本身
Record lock 總是會鎖住索引記錄,如果在建立儲存引擎表時沒有設定任何索引,innodb會使用隱式的主鍵進行鎖定
在Next-key lock 演算法下,對於行的查詢,都是這種方式,對於不同的SQL 查詢,可能設定共用的 Next-key lock,或者 排他的 Next-key lock
7. 鎖問題
鎖會並發訪問帶來了效能上的提高,但是同時也會帶來幾個問題。1) 丟失更新。2) 髒讀 3)不可重複讀取
1) 丟失更新
2) 髒讀,指的是在不同事務下,可以讀到另一個事務未提交的資料
3) 不可重複讀取,指的是在同一個事務中多次的讀取同一個資料,在這個事務還沒有結束之前,另外一個事務修改了這個資料,這是,在同一個事務的兩次讀之間,由於第2個事務的修改導致第一次事務兩次讀資料不同
髒資料和髒頁的區別:
髒頁指的是緩衝池中已經修改但是還沒有重新整理到磁碟檔案中,即資料庫記憶體中的頁和磁碟記憶體中的頁資料是不一致的。而髒資料是指緩衝池中被修改的資料,但是還沒有被提交。
對於髒頁的讀取是正常的,這並不影響資料的一致性,並且還因為是非同步,可以帶來效能上的提高,而髒資料的讀取,是一個事務讀取到了另一個事務的資料,顯然違反了事務的隔離性
髒讀和不可重複讀取的區別:
髒讀是讀到了未提交的資料,而不可重複讀取讀的是已經提交的,但是違反了事務的一致性要求
8. 阻塞
因為不同鎖之間的相容性,在有些時候,一個事務中的鎖需要等待另一個事務中的鎖釋放它所佔用的資源,在innodb中使用的是Mutex資料結構來實現,在訪問之前,需要使用mutex_enter函數進行申請,在資源訪問完成之後立即執行mutex_exit(),但一個資源被一個事務佔用時,另一個事務執行mutex_enter函數會發生阻塞
innodb中,參數innodb_lock_wait_timeout用來設定逾時的時間
9. 死結
如果程式是串列的,那麼搜尋是不可能的,死結只發生在並發訪問情況下,innodb 中有一個後台thread,用來負責查看所有可能的死結問題,並告知使用者
10 鎖定擴大
指的是當前鎖的粒度降低,eg :將行級鎖定擴大為 頁級,頁級升級為 表級
在innodb中,鎖定擴大不會帶來效能上的問題,1個鎖的開銷和100000個鎖開銷是相同的