1. 程式人生 > >MySQL表級鎖、行級鎖、頁級鎖詳細介紹

MySQL表級鎖、行級鎖、頁級鎖詳細介紹

MySQL的鎖機制比較簡單,其最顯著的特點是不同的儲存引擎支援不同的鎖機制。

MyISAM和MEMORY儲存引擎採用的是表級鎖(table-level-locking);

BDB儲存引擎採用的是頁面鎖(page-level-locking),同時也支援表級鎖;

InnoDB儲存引擎既支援行級鎖,也支援表級鎖,預設情況下是採用行級鎖。

表級,直接鎖定整張表,在你鎖定期間,其它程序無法對該表進行寫操作。如果你是寫鎖,則其它程序則讀也不允許;
行級,僅對指定的記錄進行加鎖,這樣其它程序還是可以對同一個表中的其它記錄進行操作;
頁級,表級鎖速度快,但衝突多,行級衝突少,但速度慢。所以取了折衷的頁級,一次鎖定相鄰的一組記錄。

MySQL 5.1支援對MyISAM和MEMORY表進行表級鎖定,對BDB表進行頁級鎖定,對InnoDB表進行行級鎖定。
對WRITE,MySQL使用的表鎖定方法原理如下:
如果在表上沒有鎖,在它上面放一個寫鎖。否則,把鎖定請求放在寫鎖定佇列中。

對READ,MySQL使用的鎖定方法原理如下:
如果在表上沒有寫鎖定,把一個讀鎖定放在它上面   否則,把鎖請求放在讀鎖定佇列中。

InnoDB使用行鎖定,BDB使用頁鎖定。對於這兩種儲存引擎,都可能存在死鎖。這是因為,在SQL語句處理期間,InnoDB自動獲得行鎖定和BDB獲得頁鎖定,而不是在事務啟動時獲得。 

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

三種鎖各有各的特點,若僅從鎖的角度來說,表級鎖更適合於以查詢為主,只有少量按索引條件更新資料的應用,如WEB應用;行級鎖更適合於有大量按索引條件併發更新少量不同資料,同時又有併發查詢的應用,如一些線上事務處理(OLTP)系統。

MySQL表級鎖有兩種模式:表共享讀鎖(Table Read Lock)和表獨佔寫鎖(Table Write Lock)。就是說對MyISAM表進行讀操作時,它不會阻塞其他使用者對同一表的讀請求,但會阻塞 對同一表的寫操作;而對MyISAM表的寫操作,則會阻塞其他使用者對同一表的讀和寫操作。

MyISAM表的讀和寫是序列的,即在進行讀操作時不能進行寫操作,反之也是一樣。但在一定條件下MyISAM表也支援查詢和插入的操作的併發進行,其機制是通過控制一個系統變數(concurrent_insert)來進行的。

 MyISAM鎖排程是如何實現的呢,這也是一個很關鍵的問題。例如,當一個程序請求某個MyISAM表的讀鎖,同時另一個程序也請求同一表的寫鎖,此時MySQL將會如優先處理程序呢?我們可通過指定引數low-priority-updates,使MyISAM預設引擎給予讀請求以優先的權利,設定其值為1(set low_priority_updates=1),使優先順序降低。

 InnoDB鎖與MyISAM鎖的最大不同在於:一是支援事務(TRANCSACTION),二是採用了行級鎖。我們知道事務是由一組SQL語句組成的邏輯處理單元,其有四個屬性(簡稱ACID屬性),分別為:

原子性(Atomicity):事務是一個原子操作單元,其對資料的修改,要麼全部執行,要麼全都不執行;
一致性(Consistent):在事務開始和完成時,資料都必須保持一致狀態;
隔離性(Isolation):資料庫系統提供一定的隔離機制,保證事務在不受外部併發操作影響的“獨立”環境執行;
永續性(Durable):事務完成之後,它對於資料的修改是永久性的,即使出現系統故障也能夠保持。

InnoDB有兩種模式的行鎖:

1)共享鎖:允許一個事務去讀一行,阻止其他事務獲得相同資料集的排他鎖。
    ( Select * from table_name where ......lock in share mode)

2)排他鎖:允許獲得排他鎖的事務更新資料,阻止其他事務取得相同資料集的共享讀鎖和  排他寫鎖。(select * from table_name where.....for update)
    為了允許行鎖和表鎖共存,實現多粒度鎖機制;同時還有兩種內部使用的意向鎖(都是表鎖),分別為意向共享鎖和意向排他鎖。
    InnoDB行鎖是通過給索引項加鎖來實現的,即只有通過索引條件檢索資料,InnoDB才使用行級鎖,否則將使用表鎖!

注1: FOR UPDATE僅適用於InnoDB,且必須在交易區塊(BEGIN/COMMIT)中才能生效。

另外:
添加了(行級鎖/表級鎖)鎖的資料不能被其它事務再鎖定,也不被其它事務修改(修改、刪除)
是表級鎖時,不管是否查詢到記錄,都會鎖定表
此外,如果A與B都對錶id進行查詢但查詢不到記錄,則A與B在查詢上不會進行row鎖,但A與B都會獲取排它鎖,此時A再插入一條記錄的話則會因為B已經有鎖而處於等待中,此時B再插入一條同樣的資料則會丟擲Deadlock found when trying to get lock; try restarting transaction然後釋放鎖,此時A就獲得了鎖而插入成功