MySQL設(shè)置數(shù)據(jù)庫(kù)為只讀,你會(huì)嗎?
前言:
默認(rèn)情況下,我們的 MySQL 實(shí)例是可讀寫(xiě)的。但有些情況下,我們可以將整個(gè)實(shí)例設(shè)置為只讀狀態(tài),比如做遷移維護(hù)的時(shí)候或者將從庫(kù)設(shè)為只讀。本篇文章我們來(lái)看下 MySQL 設(shè)置只讀相關(guān)知識(shí)。
1.關(guān)于 read_only 參數(shù)
MySQL系統(tǒng)中,提供有 read_only 和 super_read_only 兩個(gè)只讀參數(shù),參考官方文檔,這里介紹下這兩個(gè)參數(shù)的作用:
read_only 參數(shù)默認(rèn)不開(kāi)啟,開(kāi)啟后會(huì)阻止沒(méi)有 super 權(quán)限的用戶執(zhí)行數(shù)據(jù)庫(kù)變更操作。開(kāi)啟后,普通權(quán)限用戶執(zhí)行插入、更新、刪除等操作時(shí),會(huì)提示 --read-only 錯(cuò)誤。但具有 super 權(quán)限的用戶仍可執(zhí)行變更操作。
super_read_only 參數(shù)同樣默認(rèn)關(guān)閉,開(kāi)啟后不僅會(huì)阻止普通用戶,也會(huì)阻止具有 super 權(quán)限的用戶對(duì)數(shù)據(jù)庫(kù)進(jìn)行變更操作。
read_only 和 super_read_only 是有關(guān)聯(lián)的,二者之間的關(guān)系如下:
- 設(shè)置 super_read_only=on ,也就隱式地設(shè)置了 read_only=on。
- 設(shè)置 read_only=off ,也就隱式地設(shè)置了 super_read_only=off。
- 可以單獨(dú)開(kāi)啟 read_only 而不開(kāi)啟 super_read_only。
不過(guò),從庫(kù)開(kāi)啟 read_only 并不影響主從同步,即 salve 端仍然會(huì)讀取 master 上的日志,并且在 slave 實(shí)例中應(yīng)用日志,保證主從數(shù)據(jù)庫(kù)同步一致。(經(jīng)測(cè)試,從庫(kù)端開(kāi)啟 super_read_only 仍不影響主從同步。)
下面我們具體來(lái)操作下,看下 read_only 參數(shù)的用法:
- # 查看 read_only 參數(shù)
- mysql> show global variables like '%read_only%';
- +-----------------------+-------+
- | Variable_name | Value |
- +-----------------------+-------+
- | innodb_read_only | OFF |
- | read_only | OFF |
- | super_read_only | OFF |
- | transaction_read_only | OFF |
- | tx_read_only | OFF |
- +-----------------------+-------+
- # 動(dòng)態(tài)修改 read_only 參數(shù) (若想重啟生效 則需將 read_only = 1 加入配置文件中)
- mysql> set global read_only = 1;
- Query OK, 0 rows affected (0.00 sec)
- mysql> show global variables like 'read_only';
- +---------------+-------+
- | Variable_name | Value |
- +---------------+-------+
- | read_only | ON |
- +---------------+-------+
- # read_only 開(kāi)啟的情況下 操作數(shù)據(jù)
- # 使用超級(jí)權(quán)限用戶
- mysql> create table tb_a (a int);
- Query OK, 0 rows affected (0.05 sec)
- # 使用普通權(quán)限用戶
- mysql> create table tb_b (b int);
- ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement
- # 開(kāi)啟 super_read_only,再次使用超級(jí)權(quán)限用戶來(lái)操作數(shù)據(jù)
- mysql> set global super_read_only = 1;
- Query OK, 0 rows affected (0.00 sec)
- mysql> show global variables like 'super_read_only';
- +-----------------+-------+
- | Variable_name | Value |
- +-----------------+-------+
- | super_read_only | ON |
- +-----------------+-------+
- mysql> create table tb_c (c int);
- ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement
- # 關(guān)閉 read_only 參數(shù)
- mysql> set global read_only = 0;
- Query OK, 0 rows affected (0.00 sec)
2.flush tables with read lock 設(shè)置
除了 read_only 參數(shù)外,執(zhí)行 flush tables with read lock 也可將數(shù)據(jù)庫(kù)設(shè)置為只讀狀態(tài),那么二者有什么區(qū)別呢?我們先來(lái)了解下 flush tables with read lock 的作用。
執(zhí)行此命令會(huì)給數(shù)據(jù)庫(kù)加全局讀鎖,使得數(shù)據(jù)庫(kù)處于只讀狀態(tài),以下語(yǔ)句會(huì)被阻塞:數(shù)據(jù)更新語(yǔ)句(增刪改)、數(shù)據(jù)定義語(yǔ)句(建表、修改表結(jié)構(gòu)等)和更新類(lèi)事務(wù)的提交語(yǔ)句。下面我們來(lái)具體實(shí)驗(yàn)下:
- # 執(zhí)行FTWRL
- mysql> flush tables with read lock;
- Query OK, 0 rows affected (0.02 sec)
- # 進(jìn)行數(shù)據(jù)變更操作
- mysql> insert into tb_a values (1);
- ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock
- # 解鎖
- mysql> unlock tables;
- Query OK, 0 rows affected (0.00 sec)
- mysql> insert into tb_a values (1);
- Query OK, 1 row affected (0.01 sec)
值得注意的是,從庫(kù)端執(zhí)行 flush tables with read lock 會(huì)導(dǎo)致 SQL 線程卡住,主備延遲。與開(kāi)啟 read_only 參數(shù)不同的是,執(zhí)行 flush tables with read lock 后,其余客戶端執(zhí)行數(shù)據(jù)變更操作會(huì)持續(xù)等待而不是立即報(bào)錯(cuò),極其容易引起數(shù)據(jù)庫(kù) hang 住,執(zhí)行這個(gè)命令還是要小心的。
以個(gè)人數(shù)據(jù)庫(kù)運(yùn)維經(jīng)驗(yàn)來(lái)講,一般只有從庫(kù)需要設(shè)置只讀狀態(tài),從庫(kù)端建議開(kāi)啟 read_only 或 super_read_only,避免人為寫(xiě)入。flush tables with read lock 適用于進(jìn)行數(shù)據(jù)遷移時(shí),可以保證數(shù)據(jù)庫(kù)不發(fā)生數(shù)據(jù)改變,不過(guò)要注意及時(shí)解鎖。
總結(jié):
本篇文章主要介紹了 MySQL 只讀狀態(tài)相關(guān)知識(shí),其實(shí)除了從庫(kù)外,其余實(shí)例很少設(shè)置全局只讀,只是遇到某種需求的情況下需要將數(shù)據(jù)庫(kù)設(shè)為只讀狀態(tài),寫(xiě)本篇文章的目的也是遇到此類(lèi)需求時(shí),可以有個(gè)參考。