全局鎖和表鎖什麼場景會用到

數據庫往往是多個用戶在連接使用的,那麼**如何保證數據併發訪問的一致性、有效性呢?**首先我們看一下MySQL的鎖機制。
根據加鎖的範圍,MySQL中的鎖可分爲三類:

  • 全局鎖;
  • 表級鎖;
  • 行鎖;

1. 全局鎖

MySQL全局鎖會關閉所有打開的表,並使用全局讀鎖鎖定所有表,其命令爲:

flush tables with read lock;

當執行上面這個命令後,所有的表都變成只讀狀態,數據更新或者字段更新都將會被阻塞,可以使用下面命令解鎖:

unlock tables;

全局鎖一般會在什麼時候用到呢?
全局鎖一般用在整個庫做備份(mysqldump)時。也就是說在整個備份過程中,整個庫都是隻讀的。

  • 如果是主庫備份,會導致業務不能修改數據;
  • 如果是從庫備份,會導致主從延遲;

好在mysqldump包含一個參數–single-transaction,可以在一個事務中創建一致性快照,然後在進行所有表的備份。因此增加這個參數的情況下,備份期間可以進行數據修改。但是需要所有表都是innodb表。所以這也是建議使用InnoDB引擎的原因之一。

2. 表級鎖

表級鎖有兩種:表鎖和元數據鎖。

2.1 表鎖

表鎖使用場景:

  1. 事務需要更新某張大表的大部分或全部數據。如果使用默認的行級鎖,不僅事務執行效率低,而且可能造成其它事務長時間鎖等待或鎖衝突,這種情況下可以考慮使用表鎖來提高事務執行速度;
  2. 事務設計多個表,比較複雜,可能會引起死鎖,導致大量事務回滾,可以考慮表鎖避免死鎖;
    其中表鎖又分爲表讀鎖和表寫鎖,命令分別是:
    表讀鎖:
lock tables t1 read;
lock tables t1 write;
  • 對錶執行lock tables t1 read(表讀鎖)時,當前線程和其它線程都可以讀,本線程寫會報錯,其它線程寫會等待;
  • 對錶執行lock tables t1 write(表寫鎖)時,當前線程可以讀寫,其它線程讀寫都會造成阻塞;

2.2 元數據鎖

在MySQL中,DDL是不屬於事務範疇的。如果事務和DDL並行執行同一張表,可能會出現事務特性被破壞等bug。爲了解決這個問題,MySQL引入了元數據鎖(MDL鎖)。MDL鎖的出現解決了同一張表上事務和DDL並行執行時可能導致數據不一致的問題。很多情況下,我們需要考慮MDL的存在,否則可能導致長時間鎖等待甚至連接被打滿的情況。
比如:執行如下SQL1語句,表示10秒後返回結果:

select id, a, b, SLEEP(10) from t1 limit 1;

在此期間,執行如下兩條SQL語句:
SQL2:

alter table t1 add column c int;

SQL3:

select id, a, b from t1 limit 1;

可以看出,SQL1屬於慢SQL,在慢SQL期間,如果執行了DDL語句,即執行了SQL2,SQL2會等待(原因是SQL1在執行期間對t1加了MDL鎖,SQL2又會跟SQL1爭搶MDL鎖),再執行SQL3,SQL3也會等待,因爲SQL1沒執行結束的話,其他的所有SQL查詢都會等待。
如果出現這種情況,可以kill掉SQL1或者終止SQL2的DDL操作,讓其他查詢操作恢復。
因此在工作中應該避免慢查詢、儘量保證事務及時提交,同時避免在業務高峯執行DDL操作。

3. 總結

  • 全局鎖會讓所有的表變成只讀狀態,所有更新操作都會被阻塞,通常進行備份操作(mysqldump)時會用到全局鎖;

  • 表級鎖分爲表鎖和元數據鎖,表鎖又分爲表讀鎖和表寫鎖,兩者的區別是:

     表讀鎖:本線程和其他線程可以讀,本線程寫會報錯,其他線程寫會等待;
     表寫鎖:本線程可以讀寫,其他線程讀寫都會阻塞;	
    
  • 爲了保證事務和DDL並行執行數據一致性,引入了MDL鎖,應該注意的幾點是:

      儘量避免慢查詢;
      事務要及時提交;
      避免在業務高峯執行DDL操作;
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章