Innodb中的鎖 共用鎖和排它鎖(Shared and Exclusive Locks) 共用鎖和排它鎖是行級鎖,有兩種類型的行級鎖 共用鎖(s lock)允許持有鎖的事務對行進行讀取操作 排它鎖(x lock)允許持有鎖的事務對行進行更新和刪除操作 事務a在行r上擁有共用鎖,則其他事務可以獲得r ...
Innodb中的鎖
共用鎖和排它鎖(Shared and Exclusive Locks)
共用鎖和排它鎖是行級鎖,有兩種類型的行級鎖
共用鎖(s lock)允許持有鎖的事務對行進行讀取操作
排它鎖(x lock)允許持有鎖的事務對行進行更新和刪除操作
事務a在行r上擁有共用鎖,則其他事務可以獲得r的共用鎖,無法獲得r的排它鎖,即可讀不可寫
事務a在行r上擁有排它鎖,則其他事務既不能獲得共用鎖,也不能獲得排它鎖,即不可讀也不可寫而必須等待當前事務完成
意向鎖(Intention Locks)
意向鎖是表級鎖,用來表示將會有哪種類型的行級鎖即將被使用,有兩種類型的意向鎖
意向共用鎖(IS Locks):表明即將在表中的某一行上設置共用鎖(s lock)
意向排它鎖(Ix Locks): 表明即將在表中的某一行上設置排它鎖(x lock)
一個事務如果要獲得一個共用鎖(s lock)必須首先獲得一個意向共用鎖(is lock),一個事務如果要獲得一個排它鎖(x lock)則必須先獲得一個意向排它鎖(ix lock)
各種鎖級別的相容性
X | IX | S | IS | |
---|---|---|---|---|
X |
Conflict | Conflict | Conflict | Conflict |
IX |
Conflict | Compatible | Conflict | Compatible |
S |
Conflict | Conflict | Compatible | Compatible |
IS |
Conflict | Compatible | Compatible | Compatible |
行級鎖(Record Locks)
行級鎖總是鎖住索引記錄(index records),即便表沒有定義索引,innodb也會創建一個隱藏的聚簇索引,然後用這個索引來鎖住這一行。
間隙鎖(Gap Locks)
間隙鎖是用於索引之間或第一個索引之前或最後一個索引之後的鎖, 當語句中有一個確定的索引值的時候,間隙鎖會降級為行級鎖。例如這個
select * from child where id =100;
Next-Key Locks
不知道怎麼翻譯了。這是行級鎖和間隙鎖的組合,也就是說這種類型的鎖會做作用於一條記錄上和它之前的間隙,不允許插入。
自增鎖(AUTO-INC Locks)
一個特殊的表級鎖,用於帶有auto-increment選項的列上,它會讓你獲得連續的主鍵值。這個鎖的釋放在它的sql語句執行完成之時,而非事務結束之時,這樣其他的事務可以不必等到事務結束才獲得自增鎖。innodb_autoinc_lock_mode是用來配置這個鎖的。
Predicate Locks
謂詞鎖(不知道是不是這個意思),作用於空間索引(spatial indexes)。
常見sql語句的鎖級別
innodb預設的隔離級別是可重覆讀(repeatable read),預設的讀取方式是一致性讀(consistent read),所謂一致性讀就是在你開啟事務的時候,innodb會保存一個時間戳,在此之後的改變都是不可見的。由於innodb是一個多版本存儲引擎(multi-versioned storage engine),它會保存改變的行之前的舊的數據以支持一些事務特性,例如併發和回滾。這些數據被存儲在表空間(tablespace)的一個叫rollback segment的數據結構里。這裡的數據會被用來重建之前的值來保證一致性讀(consistent read)。
select ... from : 一致性讀,不需要鎖,除非隔離級別被設為串列化(serializable)。
select ... from ... lock in share mode :在搜索條件里的每條記錄設置共用的next-key lock, 如果有特定的索引值則為行級鎖。
select ... from ... for update :在搜索條件里的每條記錄設置排它的next-key lock, 如果有特定的索引值則為行級鎖。
update ... where... 在搜索條件里的每條記錄設置排它的next-key lock, 如果有特定的索引值則為行級鎖。
delete from ... where ... : 在搜索條件里的每條記錄設置排它的next-key lock, 如果有特定的索引值則為行級鎖。
insert 語句設置一個排它鎖在插入的行上,為行級鎖。當有多個會話嘗試插入相同主鍵發生主鍵衝突時,可能會發生死鎖,因為在發生主鍵衝突時他們各自獲得了共用鎖,而都不能獲得排它鎖。
insert ... on duplicate key update : 和之前的insert語句不同的是當發生主鍵衝突時,他們會獲得排它鎖而非共用鎖,這樣就避免了多個會話獲得共用鎖而發生死鎖。
手動加鎖
select ... from ... lock in share mode
select ... from ... for update
lock tables tb_name [AS alias {read [local] | [low_priority] write }
[,tb_name [AS alias {read [local] | [low_priority] write }...]
unlock tables;
read local允許在鎖定被保持時,執行非衝突性insert語句
low_priority write鎖定來允許其它線程在該線程正在等待write鎖時獲得read鎖