資料庫系統使用鎖是為了支援對共享資源進行併發訪問,保障資料的完整性和一致性。
不同儲存引擎的鎖設計是不一樣的,innodb 儲存引擎會在行級對資料上鎖,不過 innodb 儲存引擎也會在資料庫內部其他多個地方使用鎖。例如,操作快取池中的lru列表,刪除、新增、移動lru列表中的元素,為了保持一致性,必須有鎖的介入。myisam 儲存引擎中鎖是表鎖設計,在併發讀沒啥問題,但是相比行鎖併發寫的效能就差了很多。
innodb 儲存引擎實現了兩種標準的行級鎖:
如果乙個事務 t1 已經獲取了行 r 的共享鎖,那麼另外的事務 t2 也可以獲得行 r 的共享鎖,稱鎖相容,因為讀共享,並沒有改變資料。但如果其他事務 t3 想獲取行 r 的排他鎖,則必須等待事務 t1 和 t2 釋放行 r 上的共享鎖,稱鎖不相容。下表顯示了共享鎖和排他鎖的相容性:xs
x不相容
不相容s
不相容相容
innodb 儲存引擎支援多粒度鎖定,這種鎖定允許事務在行級上的鎖和表級上的鎖同時存在,為了支援多粒度上加鎖 innodb 儲存引擎支援一種額外加鎖方式,稱之為意向鎖。若將上鎖的物件當作有層級的樹圖來看,如果想對最細粒度上鎖就需要先對粗粒度上鎖。如下圖中,如果想對記錄 r 上 x 鎖,那麼需要分別對資料庫 a、表、頁上意向 ix 鎖,最後才能對記錄 r 上 x 鎖。
意向鎖是將鎖定的物件分為多個層次,意向鎖意味著事務希望在更細粒度上進行加鎖。意向鎖的設計比較簡練,其意向鎖即為表級鎖,目的主要為了在乙個事務中揭示下一行將被請求的鎖型別。其支援兩種意向鎖:
isixsx
is相容
相容相容
不相容ix
相容相容
不相容不相容s相容
不相容相容
不相容x
不相容不相容
不相容不相容
向乙個表新增表級 x 鎖的時候(執行 alter table, drop table, lock tables 等操作),如果沒有意向鎖的話,則需要遍歷所有整個表判斷是否有行鎖的存在,以免發生衝突。如果有了意向鎖,只需要判斷該意向鎖與即將新增的表級鎖是否相容即可。因為意向鎖的存在代表了,有行級鎖的存在或者即將有行級鎖的存在,因而無需遍歷整個表,即可獲取結果。
在 innodb 1.0 版本之前,使用者可以通過show engine innodb status
命令檢視當前鎖請求的資訊。從 innodb 1.0 版本開始,在 information_schema 架構下新增了表 innodb_trx、innodb_locks、innodb_lock_waits 三張表,使用者可以更簡單地監控當前事務和鎖狀態。表結構如下:
innodb 儲存引擎由三種行鎖演算法,如下:
next-key lock 是結合 record lock 和 gap lock 的一種鎖演算法,在 next-key lock 演算法下,innodb 儲存引擎對於行的查詢都採用的是這種鎖定方式。例如乙個索引有 10、11、13 和 20 這四個值,那麼該索引可能被 next-key locking 的區間為:(-∞,10]、(10,11]、(11,13]、(13,20]、(20,+∞)。當查詢的索引是唯一鍵(單列唯一),innodb 儲存引擎會對 next-key lock 進行優化降級為 record lock,僅需要鎖住本身即可。
next-key lock 鎖演算法解決了幻讀問題。幻讀問題是指在同乙個事務下,連續執行兩次同樣的 sql 語句可能返回不同的結果,第二次的 sql語句可能返回之前不存在的行。通過 next-key lock 演算法,即使使用者通過索引查詢乙個不存在的值,其鎖定的也是乙個範圍,另乙個事務的操作是不會執行的,這樣便避免了幻讀。
鎖等待就帶來了阻塞,在 innodb 儲存引擎中引數innodb_lock_wait_timeout
用來控制等待時間,引數innodb_rollback_on_timeout
用來設定等待超時事務是否回滾。
死鎖是指兩個或兩個以上的事務在執行過程中,因資源競爭而造成的互相等待的現象。
死鎖的四個必要條件:
若無外力作用事務將無法推進,解決死鎖問題最簡單的方法就是超時,即當兩個事務死鎖,當乙個事務達到等待閾值回滾,另乙個事務繼續執行。超時機制簡單,但如果超時的事務很大很重,回滾的代價會很大。除了超時機制,innodb 儲存引擎還提供了 wait-for graph(等待圖) 的方式進行死鎖檢測。
wait-for graph 要求資料庫儲存鎖的資訊鏈路和事務等待鏈路,通過它們構造出一張圖,而這張圖中若存在迴路就代表死鎖,因為資源間發生了相互等待。wait-for graph 是主動的死鎖檢測機制,在每個事務請求鎖並發生等待時都會判斷是否存在迴路,如果存在死鎖 innodb 儲存引擎通常選擇回滾 undo 量最小的事務,從而減少效能損耗。
鎖公升級是指粗化當前鎖的粒度,如把 1000 個行鎖公升級為乙個頁鎖。innodb 儲存引擎中不存在鎖公升級,這是因為 innodb 儲存引擎不是通過行記錄產生行鎖的,而是通過每個事務訪問的每個頁通過點陣圖對鎖進行管理,因此乙個事務不管是鎖住乙個頁的一條記錄還是多條記錄,開銷通常是一致的。
行級鎖和表級鎖
鎖定的範圍不一樣,行級鎖鎖定的是相關的行,別人仍然可以操作該錶的其他行 而表級鎖則鎖定整個表,其他人對該錶的訪問會受到更多的限制。所以,二者的主要區別就是鎖的粒度不一樣,帶來的結果及時併發能力的不同。鎖的粒度越細,併發性越好。行級鎖,一般是指排它鎖,即被鎖定行不可進行修改,刪除,只可以被其他會話se...
MySQL行級鎖 表級鎖
行級鎖 表級鎖的資料不能被其它事務再鎖定,也不被其它事務修改 修改 刪除 是表級鎖時,不管是否查詢到記錄,都會鎖定表 innodb 行鎖是通過給索引上的索引項加鎖 來實現的,這一點mysql與 oracle 不同,後者是通過在資料塊中對相應資料行加鎖來實現的。innodb這種行鎖實現特點意味著 只有...
MySQL行級鎖 表級鎖 頁級鎖
mysql資料庫由於其自身架構的特點,存在多種資料儲存引擎,每種儲存引擎所針對的應用場景特點都不太一樣,為了滿足各自特定應用場景的需求,每種儲存引擎的鎖定機制都是為各自所面對的特定場景而優化設計,所以各儲存引擎的鎖定機制也有較大區別。mysql各儲存引擎使用了三種型別 級別 的鎖定機制 表級鎖定,行...