用實例帶你了解 MySQL 全局鎖
本文轉載自微信公眾號「架構精進之路」,作者架構精進之路。轉載本文請聯(lián)系架構精進之路公眾號。
MySQL全局鎖會申請一個全局的讀鎖,對整個庫加鎖。
全局鎖的一般使用場景是:全局邏輯備份。
全局鎖的實現方式有兩種:
- //第一種方法
- Flush tables with read lock(FTWRL)
- //第二種方法
- set global readonly=true
當數據庫處于全局鎖的狀態(tài)時,其他線程的一下語句會被阻塞:數據更新語句(數據的增刪改)、數據定義語句(建表、索引變更、修改表結構等)和更新類事務的提交語句。
釋放全局鎖
- unlock tables;
來個示例吧~
創(chuàng)建數據庫 `test`
- CREATE TABLE `test` (
- `name` varchar(32) NOT NULL DEFAULT '',
- `bid` int(10) unsigned NOT NULL DEFAULT '0'
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='測試';
插入數據
- insert into test values('A', 1), ('B',2),('C',3);
查看表數據
- > select * from test;
- +------+-----+
- | name | bid |
- +------+-----+
- | A | 1 |
- | B | 2 |
- | C | 3 |
- +------+-----+
加鎖
- flush tables with read lock;
新增數據
- insert into test values('D', 4);
執(zhí)行 insert 操作后,直接返回錯誤結果:
- ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock
執(zhí)行查詢操作,可以正常返回結果:
- > select * from test;
- #返回結果:
- +------+-----+
- | name | bid |
- +------+-----+
- | A | 1 |
- | B | 2 |
- | C | 3 |
- +------+-----+
可以看到,當我們加上全局鎖的時候,數據及表更新操作都沒辦法執(zhí)行,但表查詢不受影響。這樣會給我們的業(yè)務造成很大的影響(無法修改數據),索性 Innodb 引擎的可重復讀隔離級別可以讓我們不阻塞數據變更的同時導出數據。
官方自帶的邏輯備份工具是 mysqldump。當 mysqldump 使用參數–single-transaction 的時候,導數據之前就會啟動一個事務,來確保拿到一致性視圖。而由于 MVCC 的支持,這個過程中數據是可以正常更新的。
你一定在疑惑,有了這個功能,為什么還需要 FTWRL 呢?
一致性讀是好,但前提是引擎要支持這個隔離級別。
比如,對于 MyISAM 這種不支持事務的引擎,如果備份過程中有更新,總是只能取到最新的數據,那么就破壞了備份的一致性。這時,我們就需要使用 FTWRL 命令了。
single-transaction 方法只適用于所有的表使用事務引擎的庫。
如果有的表使用了不支持事務的引擎,那么備份就只能通過 FTWRL 方法。這往往是 DBA 要求業(yè)務開發(fā)人員使用 InnoDB 替代 MyISAM 的原因之一。
用 FTWRL 而不用 set global readonly = true
- 在有些系統(tǒng)中,readonly 的值會被用來做其他邏輯,比如用來判斷一個庫是主庫還是備庫。因此,修改 global 變量的方式影響面更大,我不建議你使用。
- 在異常處理機制上有差異。如果執(zhí)行 FTWRL 命令之后由于客戶端發(fā)生異常斷開,那么 MySQL 會自動釋放這個全局鎖,整個庫回到可以正常更新的狀態(tài)。而將整個庫設置為 readonly 之后,如果客戶端發(fā)生異常,則數據庫就會一直保持 readonly 狀態(tài),這樣會導致整個庫長時間處于不可寫狀態(tài),風險較高。