mysql innodb中各類語句加鎖方式
(一)mysql innodb事務模型
(二)mysql innodb鎖模型
(三)mysql innodb非鎖定一致性讀與鎖定讀
(四)mysql innodb鎖型別及幻象讀問題
(五)mysql innodb中各類語句加鎖方式
(六)事務的提交與回滾極死鎖檢測、處理和預防
鎖定讀、update
、delete
通常在處理
sql語句的過程中在掃瞄到的每個索引記錄上加鎖,不關心
where
條件中可能排除行的非索引條件。比如,
a表有兩列i和
j,i列有索引,
j列沒索引,當前存在
(1,1)
,(1,2
),(1,3
),(1,4
),(2,1
),(2,2
),(2,3
),(2,4
)……等記錄,語句
select * from a where i=1 and j=3;
會在所有
i=1的索引記錄上加鎖,而不考慮
j=3這個條件。如果查詢中使用了輔助索引,
innodb
除了給掃瞄到的輔助索引加鎖,還會查詢到對應的聚集索引並在其上加鎖。若語句用不到合適的索引,則
mysql
會掃瞄整個表,每個錶行都會被加鎖,會阻塞其他使用者的插入操作。
innodb對不同的
sql語句加不同的鎖:
select...from讀資料庫快照,不對記錄加鎖,除非使用的是
seriallizabe
隔離級別,此時對索引記錄加
s next-key lock。
select...from...in share mode加
s next-key lock。
select...from...for updatr / update ... where ... / delete from ... where ... /加
x next-key lock。
insert在插入的索引記錄上加
x鎖,不會阻止其他事物在插入的記錄前的「間隙」插入新的記錄。插入記錄前,會設定一把
insertion intention gap lock
用以表明:不同的事務可以向同一索引「間隙」插入記錄而無需相互等待,只要其插入的位置不同。乙個事務中
insert
語句會在插入的行的索引記錄上設定一把排它鎖。如果有鍵重複的錯誤發生,則會在重複的索引記錄上設定一把共享鎖。在多個
session
同時插入同一行,且另外的某個
session
已經持有了該索引記錄的排它鎖時,共享鎖的使用可能導致死鎖的出現。
舉個例子:
create table t1 (i int, primary key (i)) engine = innodb;
session 1:
start transaction;
insert into t1 values(1);
session 2:
start transaction;
insert into t1 values(1);
session 3:
start transaction;
insert into t1 values(1);
session 1:
rollback;
三個session
:session1
會獲取行上的
x鎖,且一直持有到事務結束(提交或者回滾)。
session2
和session3
的操作會引起鍵重複的錯誤,因此會請求索引記錄上的
s鎖。因為s鎖和
x鎖不相容,這兩個鎖請求會阻塞直到
session1
中事務結束。當
session1
回滾後,釋放了持有的
x鎖,佇列中的兩個
s鎖請求會同時成功。此時
session2
與session
便會發生死鎖。因為兩個
session
中的事務都需要在插入的行上加
x鎖,而此時因其他
session
所持有的
s鎖,誰也獲取不到這個
x鎖。於是會回滾代價較小的事務解除死鎖。如果
session
是提交而非回滾,則提交後成功插入該行,事務結束、釋放x鎖。
session2.session3
中的插入因鍵重複而發生錯誤語句回滾,持有的
s鎖被釋放。
還有類似的情形,比如t1
表中已經存在某行記錄。同時
session1
中某個事務對改行進行刪除操作。
session2
、session3
中對改行進行插入操作。
session1
的事務中會在改行對應的索引記錄上新增x鎖。
session2
、session3
中的事務因鍵衝突會申請索引記錄上的s鎖。
sesession1
中的事務提交後,記錄被刪除、
x鎖釋放。
session2
和session3
中的事務獲得
s鎖。因為此時表中沒有對應的記錄所以
session2
和session3
中的事務認為可以插入。但此時會發生死鎖,因為各自在申請插入記錄上的
x鎖時相互等待對方的x鎖。
insert ... on duplicate key update 與普通
insert
語句不同,在發生鍵重複的錯誤後,在記錄上加
x next-key lock
而非 s鎖。
replace語句,無唯一鍵衝突時同
insert
,否則在記錄上加
x next-key lock。
insert into t select ... from s where ...對插入在
t表的記錄加
x鎖。若隔離級別為
read committed
或者開啟了
innodb_locks_unsafe_for_binlog
且隔離級別不為
serializable
則不對從
s中搜尋到的索引記錄加鎖,否則新增
s next-key lock。
create table ... select ... ,
replace into t select ... from s where ...
, update t ... where col in (select ... from s ...)
與insert into t select ... from s where ...
類似。
自增長與鎖: innodb
初始化自增列時會在自增列相關索引的最後一條索引記錄加鎖。這裡使用一種特殊的鎖叫
auto-inc table lock
。該鎖會在當前語句就結束後釋放而非整個事務結束後釋放,在有事務持有
auto-inc table lock
時其他事物
session
不能插入記錄。
外來鍵與鎖:若表上定義有外來鍵約束,任何需要檢查約束條件的insert
、update
、delete
操作均會在待檢查記錄上新增s鎖。
MySQL InnoDB鎖問題(五)
一 next key鎖。當我們使用範圍條件而不是相等條件去檢索資料,並請求共享鎖和排他鎖時,innodb會給符合條件的已有的資料新增上鎖 對於鍵值在條件範圍內,但不存在的記錄,叫間隙。innodb此時會給這個部分新增上鎖,這種鎖機制就是next key鎖。假如 員工表emp中只有101條資料,其em...
Mysql InnoDB儲存引擎中 死鎖
今天我們來看死鎖,死鎖的一般場景大家都能想到,只要你不是很菜,a獲取資源z之後再獲取資源x,b獲取資源x之後再獲取資源z,這樣就造成了死鎖。解釋 死鎖是指兩個或兩個以上的事務在執行過程中,因爭奪鎖資源而造成的一種互相等待的現象。解決辦法 1.超時。innodb中設定了超時時間,引數為innodb l...
Mysql InnoDB儲存引擎中 join原理
本文翻譯自mysql效能調優及架構設計 優化部分。主要是做個記錄和增加學習的廣度。實現演算法 nested loop join。本質上和我們平時使用時的直觀感受一致,選定一張驅動表作為迴圈基礎資料,然後迴圈該結果集中的資料作為過濾條件到下一張表內查詢資料,然後合併結果。如果有多個join,則將前面的...