1. 程式人生 > >MySQL各種加鎖案例分析

MySQL各種加鎖案例分析

目錄

InnoDB 鎖型別

InnoDB MVCC簡要

事務隔離級別

SQL加鎖分析(主題)

死鎖舉例分析


InnoDB鎖型別

InnoDB Lock Types

❖Shared and Exclusive Locks
❖Intention Locks
❖Record Locks
❖Gap Locks
❖Next-Key Locks
❖Insert Intention Locks
❖Auto-inc Locks
❖ Predicate Locks for Spatial Index(忽略)

InnoDB - S&X Locks

❖Row-Level Locking
❖S Locks (shared locks)
    ✓A shared (S) lock permits the transaction that holds the lock to read a row
    ✓Example: select * from xx where a=1 lock in share mode
❖X Locks ( Exclusive Locks)
    ✓An exclusive (X) lock permits the transaction that holds the lock to update or delete a row.
    ✓Example:select * from xx where a=1 for update
❖S 和 S 相容, X 和 S 互斥, X和X互斥

InnoDB - S&X Locks舉例例

❖select * from t where i=1 lock in share mode

❖select * from t where i=1 for update

插⼊入篇:如何檢視SQL加鎖資訊

❖進⾏如下設定可以看到此SQL持有鎖資訊
    ✓SET GLOBAL innodb_status_output=ON;
    ✓SET GLOBAL innodb_status_output_locks=ON;
    ✓5.6.16版本引⼊此引數,影響效能,線上慎開

插⼊入篇:檢視SQL加鎖資訊

InnoDB - Intention Locks

❖InnoDB⽀持多粒度鎖,允許⾏鎖和表鎖並存
❖Table-Level Locks
❖Intention shared Lock(IS) 意味著事務需要在表的⾏上⾯新增S鎖,因此獲取S鎖之前需要獲取IS鎖
❖ Intention exclusive Lock(IX)意味著事務需要在表的⾏上⾯新增X鎖,因此獲取X鎖之前需要獲取IX鎖

InnoDB - 相容性

InnoDB - Record Locks

❖記錄鎖是對索引加鎖,⽽不是具體的資料⾏
❖即使表沒有定義索引,InnoDB產⽣隱藏聚簇索引⽤於加鎖

InnoDB - Gap Locks

❖A gap lock is a lock on a gap between index records, or a lock on the gap before the first or after the last index record.
❖A gap might span a single index value, multiple indexvalues, or even be empty.
❖Gap可能通過設定Read-Commited以及innodb_locks_unsafe_for_binlog進⾏顯⽰關閉

InnoDB - Next-Key Locks

❖A next-key lock is a combination of a record lock on the index record and a gap lock on the gap before the index record.

❖InnoDB 預設的事務隔離級別是REPEATABLE READ
❖在RR模式下, InnoDB 使⽤ next-key locks 防⽌幻讀

InnoDB - Next-Key Locks舉例例1

InnoDB - Next-Key Locks舉例例2

InnoDB - Insert Intention Locks

❖An insert intention lock is a type of gap lock set by INSERT operations prior to row insertion.

InnoDB - Insert Intention Locks

InnoDB - AUTO-INC Locks

❖特殊的table-level lock
❖持有時間在當前sql執⾏完成就釋放,⽽不是事務結束後才釋放
❖通過引數innodb_autoinc_lock_mode控制,具體有三種模式:
    AUTOINC_OLD_STYLE_LOCKING (0)
    AUTOINC_NEW_STYLE_LOCKING (1) 保證Id連續,預設
    AUTOINC_NO_LOCKING (2)

InnoDB - AUTO-INC Locks

AUTOINC_OLD_STYLE_LOCKING(0)
    1)在分⽚片前加上AUTO_INC鎖,並在SQL結束時釋放掉

AUTOINC_NO_LOCKING (2)
    1)只在分配時加個mutex即可很快就釋放
    2)在statement格式下不不能保證批量量插⼊入的複製安全性

InnoDB MVCC

資料庫併發控制協議

1、基於鎖的協議 (Lock Based Protocol)
2、基於多版本機制 (Multi-version Protocol)
3、基於時間的協議 (Time-Stamp Ordering Protocol)
4、基於圖的協議 (Graph Based Protocol)
5、基於多粒度協議 (Multiple Granularity Protocol)

MVCC

❖多版本控制
❖相對於基於鎖的協議,MVCC最⼤好處:讀不加鎖,讀寫不衝突
❖讀操作
    ✓快照讀(snapshot read)
    ✓當前讀(current read)

快照讀和當前讀

❖快照讀:簡單select操作,不加鎖
    ❖select * from table where ?
❖ 當前讀: 特殊讀操作,插⼊/更新/刪除,需要加鎖
    ❖select * from table where ? lock in share mode
    ❖select * from table where ? for update
    ❖insert into table values (…)
    ❖delete from table where ?
    ❖update table set ? where ?

InnoDB MVCC實現關鍵點

❖ROW記錄格式
❖ROW和Undo關係
❖ReadView判斷

InnoDB MVCC實現原理理-Row格式

實際上還有⼀個欄位DB_ROW_ID,只出現在聚簇索引中

InnoDB MVCC實現原理理-Row和Undo

❖通過回滾段實現多個版本的讀取

InnoDB MVCC實現原理理-Read View

InnoDB MVCC實現原理理-可⻅見性判斷

事務隔離級別

讀現象問題

❖丟失更新 (事務ACID保證不會發⽣)
❖髒讀
❖不可重複讀
❖幻讀

事務隔離級別

❖Read Uncommitted
   ✓可以讀取未提交的事務,此隔離級別不會使⽤。
❖Read committed (RC)
   ✓針對當前讀,RC隔離級別保證對讀取到的記錄加鎖(⾏鎖),存在幻讀現象。
❖Repeatable Read(RR)
   ✓針對當前讀,RR保證對讀取到的記錄加鎖(⾏鎖),同時保證對讀取的範圍加鎖,新的滿⾜查詢條件的記錄不能夠插⼊(Next-Key Locks),不存在幻讀現象。
❖Serializable
    ✓從MVCC併發控制退化為基於鎖的併發控制。所有的讀操作都為當前讀,讀加讀鎖(S鎖),寫加寫鎖(X鎖)。Serializable隔離級別下,讀寫衝突,併發度急劇下降。

讀現象和事務隔離級別舉例例

讀現象舉例例-髒讀

❖髒讀:當⼀個事務允許讀取另⼀個事務修改但未提交的資料時,就可能發⽣髒讀。

讀現象舉例例-不不可重複讀

❖不可重複讀:在⼀次事務中,當⼀⾏資料獲取兩遍得到不同的結果表⽰發⽣了“不可重複讀”

讀現象舉例例-幻讀

❖ 幻讀:不可重複讀的⼀種特殊場景。當事務1兩次執⾏SELECT ... WHERE檢索⼀定範圍內資料的操作中間,事務2在這個表中建立了(如INSERT)⼀⾏新資料,這條新資料正好滿⾜事務1的“WHERE”⼦句。

標準事務隔離級別

❖標準事務隔離級別中RR沒有解決幻讀問題。

InnoDB在RR模式解決幻讀問題舉例例

SQL加鎖分析

❖簡單SQL加鎖分析
❖複雜SQL加鎖分析
❖常見SQL加鎖總結

Update操作加鎖流程

2PL:Two-Phase Locking

一條簡單SQL的加鎖分析-問題

❖SQL1:select * from t1 where id = 10
    ✓MVCC多版本控制,Select 快照讀,不加鎖
❖SQL2: delete from t1 where id = 10

一條簡單SQL的加鎖分析-前提條件

❖前提⼀:id列是不是主鍵?
❖前提⼆:當前系統的事務隔離級別是什麼?
❖前提三:id列如果不是主鍵,那麼id列上是否有索引嗎?
❖前提四:id列上如果有⼆級索引,那麼這個索引是唯⼀索引嗎?
❖前提五:SQL的執⾏計劃是什麼?索引掃描?全表掃描?

SQL加鎖分析前提場景

❖組合⼀:id列是主鍵,RC事務隔離級別
❖組合⼆:id列是⼆級唯⼀索引,RC事務隔離級別
❖組合三:id列是⼆級⾮唯⼀索引,RC事務隔離級別
❖組合四:id列上沒有索引,RC事務隔離級別
❖組合五:id列是主鍵,RR事務隔離級別
❖組合六:id列是⼆級唯⼀索引,RR事務隔離級別
❖組合七:id列是⼆級⾮唯⼀索引,RR事務隔離級別
❖組合⼋:id列上沒有索引,RR事務隔離級別
❖組合九:Serializable事務隔離級別

組合⼀一:id主鍵+RC

組合⼆二:id唯⼀一索引+RC

複雜SQL加鎖規則