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

來源:互聯網
上載者:User

標籤:style   ar   io   使用   sp   for   on   資料   div   

這篇文章主要介紹了MySQL行級鎖、表級鎖、頁級鎖詳細介紹,同時列舉了一些執行個體說明,需要的朋友可以參考下  

頁級:引擎 BDB。
表級:引擎 MyISAM , 理解為鎖住整個表,可以同時讀,寫不行
行級:引擎 INNODB , 單獨的一行記錄加鎖

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

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

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

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

行級鎖定的優點:
·         當在許多線程中訪問不同的行時只存在少量鎖定衝突。
·         復原時只有少量的更改。
·         可以長時間鎖定單一的行。

行級鎖定的缺點:
·         比頁級或表級鎖定佔用更多的記憶體。
·         當在表的大部分中使用時,比頁級或表級鎖定速度慢,因為你必須擷取更多的鎖。
·         如果你在大部分資料上經常進行GROUP BY操作或者必須經常掃描整個表,比其它鎖定明顯慢很多。
·         用進階別鎖定,通過支援不同的類型鎖定,你也可以很容易地調節應用程式,因為其鎖成本小於行級鎖定。

在以下情況下,表鎖定優先於頁級或行級鎖定:
·         表的大部分語句用於讀取。
·         對嚴格的關鍵字進行讀取和更新,你可以更新或刪除可以用單一的讀取的關鍵字來提取的一行:
·                UPDATE tbl_name SET column=value WHERE unique_key_col=key_value;
·                DELETE FROM tbl_name WHERE unique_key_col=key_value;
·         SELECT 結合并行的INSERT語句,並且只有很少的UPDATE或DELETE語句。
·         在整個表上有許多掃描或GROUP BY操作,沒有任何寫操作。

/* ========================= mysql 鎖表類型和解鎖語句 ========================= */

如果想要在一個表上做大量的 INSERT 和 SELECT 操作,但是並行的插入卻不可能時,可以將記錄插入到暫存資料表中,然後定期將暫存資料表中的資料更新到實際的表裡。可以用以下命令實現:

複製代碼代碼如下:
mysql> LOCK TABLES real_table WRITE, insert_table WRITE;
mysql> INSERT INTO real_table SELECT * FROM insert_table;
mysql> TRUNCATE TABLE insert_table;
mysql> UNLOCK TABLES;

 

行級鎖的優點有:
 在很多線程請求不同記錄時減少衝突鎖。
 交易回復時減少改變資料。
 使長時間對單獨的一行記錄加鎖成為可能。

行級鎖的缺點有:
 比頁級鎖和表級鎖消耗更多的記憶體。
 鎖是電腦協調多個進程或線程並發訪問某一資源的機制,不同的資料庫的鎖機制大同小異。由於資料庫資源是一種供許多使用者共用的資源,所以如何保證資料並發訪問的一致性、有效性是所有資料庫必須解決的一個問題,鎖衝突也是影響資料庫並發訪問效能的一個重要因素。瞭解鎖機制不僅可以使我們更有效開發利用資料庫資源,也使我們能夠更好地維護資料庫,從而提高資料庫的效能。

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

例如,MyISAM和MEMORY儲存引擎採用的是表級鎖(table-level-locking);BDB儲存引擎採用的是頁面鎖(page-level-locking),同時也支援表級鎖;InnoDB儲存引擎既支援行級鎖,也支援表級鎖,預設情況下是採用行級鎖。

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

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

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

     MyISAM表的讀和寫是串列的,即在進行讀操作時不能進行寫操作,反之也是一樣。但在一定條件下MyISAM表也支援查詢和插入的操作的並發進行,其機制是通過控制一個系統變數(concurrent_insert)來進行的,當其值設定為0時,不允許並發插入;當其值設定為1 時,如果MyISAM表中沒有空洞(即表中沒有被刪除的行),MyISAM允許在一個進程讀表的同時,另一個進程從表尾插入記錄;當其值設定為2時,無論MyISAM表中有沒有空洞,都允許在表尾並發插入記錄。

     MyISAM鎖調度是如何?的呢,這也是一個很關鍵的問題。例如,當一個進程請求某個MyISAM表的讀鎖,同時另一個進程也請求同一表的寫鎖,此時MySQL將會如優先處理進程呢?通過研究表明,寫進程將先獲得鎖(即使讀請求先到鎖等待隊列)。但這也造成一個很大的缺陷,即大量的寫操作會造成查詢操作很難獲得讀鎖,從而可能造成永遠阻塞。所幸我們可以通過一些設定來調節MyISAM的調度行為。我們可通過指定參數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才使用行級鎖,否則將使用表鎖!

另外:插入,更新效能最佳化的幾個重要參數

代碼如下:
bulk_insert_buffer_size
批量插入緩衝大小, 這個參數是針對MyISAM儲存引擎來說的.適用於在一次性插入100-1000+條記錄時, 提高效率.預設值是8M.可以針對資料量的大小,翻倍增加.

 

concurrent_insert
並發插入, 當表沒有空洞(刪除過記錄), 在某進程擷取讀鎖的情況下,其他進程可以在表尾部進行插入.

值可以設0不允許並發插入, 1當表沒有空洞時, 執行並發插入, 2不管是否有空洞都執行並發插入.
預設是1 針對錶的刪除頻率來設定.

delay_key_write
針對MyISAM儲存引擎,延遲更新索引.意思是說,update記錄時,先將資料up到磁碟,但不up索引,將索引存在記憶體裡,當表關閉時,將記憶體索引,寫到磁碟. 值為 0不開啟, 1開啟. 預設開啟.

delayed_insert_limit, delayed_insert_timeout, delayed_queue_size
延遲插入, 將資料先交給記憶體隊列, 然後慢慢地插入.但是這些配置,不是所有的儲存引擎都支援, 目前來看, 常用的InnoDB不支援, MyISAM支援. 根據實際情況調大, 一般預設夠用了


/* ==================== MySQL InnoDB 鎖表與鎖行 ======================== */

 

由於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;

 

例3: (無主鍵,table lock)

代碼如下:SELECT * FROM products WHERE name=‘Mouse‘ FOR UPDATE;

 

例4: (主鍵不明確,table lock)

代碼如下:

SELECT * FROM products WHERE id<>‘3‘ FOR UPDATE;

 

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

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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.