innodb儲存引擎實現了如下兩種標準的行級鎖:
如果乙個事務t1已經獲取行r的共享鎖,那麼另外的事務t2可以立即獲得行r的共享鎖,因為讀取並沒有改變行r的資料,這種情況稱為鎖相容(lock compatible)。但是若有其他的事務t3想獲得行r的排他鎖,則必須等待事務t1、t2釋放行r上面的共享鎖,這種情況稱為鎖不相容。
另外innodb還支援意向鎖(intention lock),具體是將鎖定的物件分為多個層次,意向鎖意味著事務希望在更細粒度上進行加鎖(其實具體有啥用我還是不太懂)。innodb儲存引擎支援意向鎖設計比較簡練,其意向鎖即為表級別的鎖,設計目的主要是為了在乙個事務中揭示下一行將被請求的鎖型別(???)。其支援兩種意向鎖:
一致性的非鎖定讀(consistent nonlocking read)是指innodb儲存引擎通過行多版本控制(multi versioning)的方式來讀取當前執行時間資料庫中行的資料。如果讀取的行正在執行delete或update操作,這時讀取操作不會因此去等待行上鎖的釋放。innodb儲存引擎會去讀取行的乙個快照資料。其實,我感覺這個就是傳說中的mvcc。
乙個行記錄可能有不止乙個快照資料,一般稱這種技術為行多版本技術。由此帶來的併發控制,稱之為多版本併發控制(multi version concurrency control,mvcc)(哈哈)。
在read committed事務隔離級別下,對於快照資料,非一致性讀總是讀取被鎖定行的最新乙份快照資料。而在repeatable read事務隔離級別下,對於快照資料,非一致性讀總是讀取事務開始時的行資料版本。
在某些情況下,使用者需要顯式地對資料庫讀取操作進行加鎖以保證資料邏輯的一致性。innodb儲存引擎對於select語句支援兩種一致性的鎖定讀操作:
注意,上述兩個語句必須在乙個事務中,當事務提交了,鎖也就釋放了。因此在使用上述兩句select鎖定語句時,務必加上begin,start transaction或者set autocommit=0。(我尋思著,即使開了autocommit,那不是每條語句都相當於乙個事務嗎???)
innodb儲存引擎有三種行鎖的演算法,其分別是:
gap lock的作用是為了阻止多個事務將記錄插入到同乙個範圍內,而這會導致phantom problem(幻影問題)的產生。
從效能上看,read committed 不會優於預設的事務隔離級別read repeatable。
在預設的事務隔離級別下,即repeatable read下,innodb儲存引擎採用next-key locking機制來避免phantom problem(幻象問題)。這點可能不同於其他的資料庫,如oracle資料庫,因為其可能需要在serializable的事務隔離級別下才能解決phantom problem。
phantom problem是指在同一事務下,連續執行兩次同樣的sql語句可能導致不同的結果,第二次的sql語句可能會返回之前不存在的行。
髒讀指的是在不同的事務下,當前事務可以讀到另外事務未提交的資料。髒讀發生的條件是需要事務的隔離級別為read uncommitted。
在第乙個事務中的兩次讀資料之間,由於第二個事務的修改,那麼第乙個事務兩次讀到的資料可能是不一樣的。這樣就發生了在乙個事務內兩次讀到的資料是不一樣的情況,這種情況稱為不可重複讀。
一般來說,不可重複讀的問題是可以接受的,因為其讀到的是已經提交的資料,本身並不會帶來很大的問題。因此,很多資料庫廠商將其資料庫事務的預設隔離級別設定為read committed,在這種隔離級別下允許不可重複讀的現象。但是innodb的預設隔離級別是repeatable read。
在innodb儲存引擎中,通過使用next-key lock 演算法來避免不可重複讀的問題。在mysql官方文件中將不可重複讀的問題定義為phantom problem,即幻象問題。(???這就是我疑惑的地方,網上不都是把幻影讀和不可重複讀分開的嗎?但是我想了一下,要說這兩個是同乙個東西也可以。因為這兩個問題都是乙個事務讀到了另乙個事務所提交的修改。)
丟失更新是另乙個鎖導致的問題,簡單來說其就是乙個事務的更新操作會被另乙個事務的更新操作所覆蓋,從而導致資料的不一致。
但是,在當前資料庫的任何隔離級別下,都不會導致資料庫理論意義上的丟失更新問題。這是因為,即使是read uncommitted的事務隔離級別,對於行的dml操作,需要對行或其他粗粒度級別的物件加鎖。
雖然資料庫能阻止丟失更新問題的產生,但是在生產應用中還有另乙個邏輯意義的丟失更新問題,而導致該問題的並不是因為資料庫本身的問題。實際上,在所有多使用者計算機系統環境下都有可能產生這個問題。要避免丟失更新發生,需要讓事務在這種情況下的操作變成序列化,而不是並行的操作。
丟失更新是程式設計師最容易犯的錯誤,也是最不易發現的乙個錯誤,因為這種現象只是隨機的、零星出現的,不過其可能造成的後果卻十分嚴重。(丟失更新這點我還是沒太明白,真的感覺很難避免)
innodb儲存引擎通過引數innodb_lock_wait_timeout來控制等待的時間(預設是50秒),通過引數innodb_rollback_on_timeout來設定是否在等待超時時對進行中的事務進行回滾操作(預設是off,代表不回滾)。
需要牢記的是,在預設情況下innodb儲存引擎不會回滾超時引發的錯誤異常。其實innodb儲存引擎在大部分情況下都不會對異常進行回滾。如果在乙個會話中丟擲了超時異常,但是既沒有進行commit操作,也沒有進行rollback操作。而這是十分危險的狀態,因此使用者必須判斷是否需要commit還是rollback,之後再進行下一步的操作。
死鎖是指兩個或兩個以上的事務在執行過程中,因爭奪鎖資源而造成的一種互相等待的現象。
對於死鎖,我感覺要知道的就是innodb會主動地去進行死鎖檢測。若存在死鎖,通常來說innodb儲存引擎會選擇回滾undo量最小的事務。
鎖公升級(lock escalation)是指將當前鎖的粒度降低。
innodb儲存引擎不存在鎖公升級的問題。因為其不是根據每個記錄來產生鎖的,相反,其根據每個事務訪問的每個頁對鎖進行管理,採用的是點陣圖的方式。因此不管乙個事務鎖住頁中乙個記錄還是多個記錄,其開銷通常都是一致的。(好吧,我只是寫上,其實我理解不了。。。)
Mysql InnoDB儲存引擎的鎖相關
mysql rr 為啥能隔離幻讀 innodb提供了一致性的非鎖定讀 行級鎖支援 lock 與latch lock 行級鎖 意向鎖 事務在更細的粒度上加鎖 一致性的非鎖定讀 一致性鎖定讀 自增長與鎖 外來鍵和鎖 行鎖的三種演算法 gap lock 間隙鎖,鎖定乙個範圍,不包含記錄本身 next ke...
MySQL鎖相關內容
mysql的表鎖使用 lock table 表名 read write 語句來新增讀鎖或者寫鎖。通過unlock table 語句來釋放所有表鎖。在對錶加了表鎖時,這個連線就不能再操作其他表了 包括讀和寫 簡而言之,就是讀鎖會阻塞寫,但是不會阻塞讀。而寫鎖則會把讀和寫都阻塞。還有一點就是網上都說表鎖...
InnoDB 儲存引擎
innodb是事務型資料庫的首選引擎,支援事務安全表 acid 支援行鎖定和外來鍵。mysql 5.5.5 之後,innodb作為預設儲存引擎。innodb的主要特性有一下幾項。a.innodb給mysql提供了具有提交 回滾和崩潰恢復能力的事務安全 acid相容 儲存引擎。innodb鎖定在行級並...