1. 程式人生 > >MySQL鎖(二)表鎖:為什麼給小表加欄位會導致整個庫掛掉?

MySQL鎖(二)表鎖:為什麼給小表加欄位會導致整個庫掛掉?

## 概述 表級鎖是MySQL中鎖定粒度最大的一種鎖,表示對當前操作的整張表加鎖,它實現簡單,資源消耗較少,被大部分MySQL引擎支援。最常使用的MYISAM與INNODB都支援表級鎖定。表級鎖定分為表共享讀鎖(共享鎖)與表獨佔寫鎖(排他鎖)。 特點:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發出鎖衝突的概率最高,併發度最低。 MySQL 中表級鎖有兩種:一種是表鎖,另一種是元資料鎖(meta data lock, MDL)。 ## 表鎖 表鎖的語法是 lock tables...read/write。與 FTWRL 類似,可以使用 unlock tables 主動釋放鎖,或者在客戶端斷開連結時自動釋放。 在還沒有出現更細粒度的鎖之前,表鎖是最常用於處理併發的。而對 InnoDB 這種支援行鎖的引擎,一般不使用 lock tables 命令來控制併發。 ## MDL 另一類表級的鎖是MDL。MDL不需要顯式使用,在訪問一個表的時候會被自動加上。 在MySQL 5.5版本中引入MDL,當對一個表做 CURD 時,加 MDL 讀鎖;當要對錶做 DDL 時,加 MDL 寫鎖; - 讀鎖之間不互斥。 - 讀寫鎖之間、寫鎖之間互斥。 有時候給一個小表加個欄位,可能會導致整個庫掛掉。假設表 t 是一個小表。
圖1 給表 t 加欄位 會話A加了 MDL 讀鎖;會話B也加了 MDL 讀鎖,可以正常執行;會話C被阻塞,等待會議A釋放 MDL 讀鎖。 如果只是會話C被阻塞倒沒關係,但之後所有在表 t 上新申請MDL 讀鎖都會被會議C阻塞。也就是這個表現在完全不能讀寫了。 ### 如何安全地給小表加欄位? 很簡單,在 `ALTER TABLE` 加等待時間。如果超過等待時間後,操作回滾。 MariaDB 已經合併了 AliSQL 的這個功能,所以這兩個開源分支目前都支援 DDL NOWAIT/WAIT n 這個語法。 ``` ALTER TABLE tbl_name NOWAIT add column ... ALTER TABLE tbl_name WAIT N add column ... ``` ## 參考資料 - [06 | 全域性鎖和表鎖 :給表加個欄位怎麼有這麼多阻礙?](https://time.geekbang.org/column/article/69862)