Mysql InnoDB 行鎖和表鎖介紹

 

mysql 的 InnoDB引擎支持行鎖,與Oracle不一樣,mysql的行鎖是經過索引加載的,便是行鎖是加在索引響應的行上的,要是對應的SQL語句沒有走索引,則會全表掃描,行鎖則沒法實現,取而代之的是表鎖mysql

 

先介紹幾個名詞sql

表鎖:不會出現死鎖,發生鎖衝突概率高,併發低併發

行鎖:會出現死鎖,發生鎖衝突概率低,併發高spa

鎖衝突:例如說事務A將某幾行上鎖後,事務B又對其上鎖,鎖不能共存不然會出現鎖衝突。(可是共享鎖能夠共存,共享鎖和排它鎖不能共存,排它鎖和排他鎖也不能夠)code

死鎖:例如說兩個事務,事務A鎖住了1~5行,同時事務B鎖住了6~10行,此時事務A請求鎖住6~10行,就會阻塞直到事務B施放6~10行的鎖,而隨後事務B又請求鎖住1~5行,事務B也阻塞直到事務A釋放1~5行的鎖。死鎖發生時,會產生Deadlock錯誤。鎖是對錶操做的,因此天然鎖住全表的表鎖就不會出現死鎖。索引

 

行鎖的類型事務

共享鎖又稱:讀鎖。當一個事務對某幾行上讀鎖時,容許其餘事務對這幾行進行讀操做,但不容許其進行寫操做,也不容許其餘事務給這幾行上排它鎖,但容許上讀鎖。table

排它鎖又稱:寫鎖。當一個事務對某幾個上寫鎖時,不容許其餘事務寫,但容許讀。更不容許其餘事務給這幾行上任何鎖。包括寫鎖。test

共享鎖的寫法:lock in share mode表單

select  * from  test where math>60 lock in share mode;

排它鎖的寫法:for update

select * from test where math >60 for update;

 

行鎖的實現

注意幾點

1.行鎖必須有索引才能實現,不然會自動鎖全表

2.兩個事務不能鎖同一個索引

事務A先執行:
select * from test where math>60 for update;
 
事務B再執行:
select * from test where math<60 for update;

這樣的話,事務B是會阻塞的。若是事務B把 math索引換成其餘索引就不會阻塞,
但注意,換成其餘索引鎖住的行不能和math索引鎖住的行有重複。

 

行鎖示例

因爲InnoDB預設是Row-Level Lock,因此只有「明確」的指定主鍵,MySQL纔會執行Row lock (只鎖住被選取的資料例) ,不然MySQL將會執行Table Lock (將整個資料表單給鎖住)。
舉個例子:
假設有個表單products ,裏面有id跟name二個欄位,id是主鍵。
例1: (明確指定主鍵,而且查詢有數據,row lock)
SELECT * FROM products WHERE id='3' FOR UPDATE;
 
SELECT * FROM products WHERE id='3' and type=1 FOR UPDATE;
 
 
 
例2: (明確指定主鍵,若查詢無數據,無lock)
 
SELECT * FROM products WHERE id='-1' FOR UPDATE;
 
 
 
例2: (無主鍵,table lock)
 
SELECT * FROM products WHERE name='Mouse' FOR UPDATE;
 
 
 
例3: (主鍵不明確,table lock)
 
SELECT * FROM products WHERE id<>'3' FOR UPDATE;
 
 
 
例4: (主鍵不明確,table lock)
 
SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;
 
 
 
注1: FOR UPDATE僅適用於InnoDB,且必須在(BEGIN/COMMIT)中才能生效
相關文章
相關標籤/搜索