1. 程式人生 > >MYSQL的鎖介紹,以及死鎖發生情況-帶例子

MYSQL的鎖介紹,以及死鎖發生情況-帶例子

  mysql鎖能在併發情況下的mysql進行更好的優化

MySQL有三種鎖的級別:頁級、表級、行級,這3種鎖的特性可大致歸納如下: 
表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖衝突的概率最高,併發度最低。
行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。
頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間;會出現死鎖;鎖定粒度界於表鎖和行鎖之間,併發度一般。

     由於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)中才能生效。

注2: 要測試鎖定的狀況,可以利用MySQL的Command Mode ,開二個視窗來做測試。

 

在MySql 5.0中測試確實是這樣的

另外:MyAsim 只支援表級鎖,InnerDB支援行級鎖

添加了(行級鎖/表級鎖)鎖的資料不能被其它事務再鎖定,也不被其它事務修改(修改、刪除)

是表級鎖時,不管是否查詢到記錄,都會鎖定表

死鎖:

什麼是死鎖,在網上摘抄一段通俗的說法:

老闆要你做個事情,然後老闆在等你做好後彙報結果給他。然後,現在你去忙這件事情了。在你還沒做完這件事的時候,你的老闆想再次的叫你做另一件事,於是,他到你的辦公室找你,而你這時候已經做完前面的事情去了老闆的辦公室想彙報結果。你們兩看到對方不在辦公室,就在對方辦公室一直等待,那麼你就無法等到老闆,你的老闆也等不到你,這樣就死鎖了。

解決辦法,1、一般解決這樣的情況,就是增加一個祕書,你開始做什麼事情了。是否結束了。他都有記錄。老闆要下達命令前,先詢問祕書就可以了。如果你正在忙,就稍微的等一會。這就是類似的情況。祕書相當於執行緒互斥的物件,用於同步兩個執行緒。2、首先你要給執行緒(你自己一個手機,或者祕書)  然後儘量監測自己的狀態是否死鎖了。
外圍管理執行緒(你的老闆也要有辦法聯絡你,比如給你打電話)給你的訊息佇列插命令、 或者檢查你執行了多少時間或者迴圈次數。是在不行就吧你殺了,再招一個工人 


那麼現在看看mysql的死鎖:如果A與B都對錶id進行查詢但查詢不到記錄,則A與B在查詢上不會進行row鎖,但A與B都會獲取排它鎖,此時A再插入一條記錄的話則會因為B已 經有鎖而處於等待中,此時B再插入一條同樣的資料則會丟擲 Deadlock found when trying to get lock; try restarting transaction然後釋放鎖, 此時A就獲得了鎖而插入成功

相關: