技術分享 | 何時需要手動重新整理授權表

愛可生雲資料庫發表於2022-03-01

作者:楊濤濤

資深資料庫專家,專研 MySQL 十餘年。擅長 MySQL、PostgreSQL、MongoDB 等開源資料庫相關的備份恢復、SQL 調優、監控運維、高可用架構設計等。目前任職於愛可生,為各大運營商及銀行金融企業提供 MySQL 相關技術支援、MySQL 相關課程培訓等工作。

本文來源:原創投稿

*愛可生開源社群出品,原創內容未經授權不得隨意使用,轉載請聯絡小編並註明來源。


本篇來源於客戶諮詢的問題。

問題概要為:記憶中在 MySQL 裡對使用者進行授權操作後都需要執行 flush privileges 才能生效,怎麼我在你寫的涉及到使用者授權相關的文章裡都沒有看到執行 flush privileges 語句?

對於這個問題的解答,首先得明白語句 flush privileges 的作用是什麼?flush privileges 是 flush 語句集合裡的一條子項,執行它的作用是來同步 MySQL 磁碟和記憶體中的授權資料,讓其保持一致。說詳細點就是全量讀取授權表的磁碟資料並且完全覆蓋記憶體中的授權資料,又或者反著同步磁碟上的授權資料。
具體可以參考官網手冊連結:https://dev.mysql.com/doc/ref...

接下來用兩個簡單示例說明執行 flush privileges 語句的時機。
第一,何時使用?
當授權資料在磁碟和記憶體中不一致時,存在兩種時機:一是記憶體資料較新;另一個則是磁碟資料較新。當這兩點中的任意一點存在時都需要執行 flush privileges 語句。
比如直接對錶 mysql.user 執行 DML 語句,那麼此時磁碟資料較新,需要手動執行 flush privileges 語句來覆蓋記憶體中的授權資料。

舉個例子,使用者 ytt_u1 擁有的許可權資料如下:

mysql:(none)>show grants for ytt_u1;
+-------------------------------------+
| Grants for ytt_u1@%                 |
+-------------------------------------+
| GRANT SELECT ON *.* TO `ytt_u1`@`%` |
+-------------------------------------+
1 row in set (0.00 sec)

管理員來直接更新底層使用者表資料: 取消 select 許可權。

mysql:(none)>update mysql.user set select_priv='N' where user ='ytt_u1';
Query OK, 1 row affected (0.07 sec)
Rows matched: 1  Changed: 1  Warnings: 0

複查使用者 ytt_u1 擁有的許可權資料:結果沒有同步。

mysql:(none)>show grants for ytt_u1;
+-------------------------------------+
| Grants for ytt_u1@%                 |
+-------------------------------------+
| GRANT SELECT ON *.* TO `ytt_u1`@`%` |
+-------------------------------------+
1 row in set (0.00 sec)

手動執行 flush privileges 語句:再次檢視使用者 ytt_u1 的許可權資料,資料已經同步為最新。

mysql:(none)>flush privileges;
Query OK, 0 rows affected (0.12 sec)

mysql:(none)>show grants for ytt_u1;
+------------------------------------+
| Grants for ytt_u1@%                |
+------------------------------------+
| GRANT USAGE ON *.* TO `ytt_u1`@`%` |
+------------------------------------+
1 row in set (0.00 sec)
第二,何時不需要使用?
MySQL 內部命令自動更新或者刪除使用者授權資料。

比如 create user 、grant 、revoke 等語句執行後會自動同步授權資料,如無異常,則不需要手動執行 flush privileges 語句。舉個例子:還是使用者ytt_u1,檢視最新許可權資料,結果顯示沒有任何許可權。

mysql:(none)>show grants for ytt_u1;
+------------------------------------+
| Grants for ytt_u1@%                |
+------------------------------------+
| GRANT USAGE ON *.* TO `ytt_u1`@`%` |
+------------------------------------+
1 row in set (0.00 sec)

用 grant 語句來給使用者 ytt_u1 賦予資料庫 ytt 的只讀許可權:

mysql:(none)>grant select on ytt.* to ytt_u1;
Query OK, 0 rows affected (0.20 sec)

檢視使用者 ytt_u1 的許可權資料:資料已經同步為最新。

mysql:(none)>show grants for ytt_u1;
+-----------------------------------------+
| Grants for ytt_u1@%                     |
+-----------------------------------------+
| GRANT USAGE ON *.* TO `ytt_u1`@`%`      |
| GRANT SELECT ON `ytt`.* TO `ytt_u1`@`%` |
+-----------------------------------------+
2 rows in set (0.00 sec)

再來看下取消授權操作是否也會同步最新授權資料:

mysql:(none)>revoke select on ytt.* from ytt_u1;
Query OK, 0 rows affected (0.09 sec)

檢視使用者 ytt_u1 的許可權資料:資料也是及時同步的。

mysql:(none)>show grants for ytt_u1;
+------------------------------------+
| Grants for ytt_u1@%                |
+------------------------------------+
| GRANT USAGE ON *.* TO `ytt_u1`@`%` |
+------------------------------------+
1 row in set (0.00 sec)
所以只要按照 MySQL 內建的使用者管理語句來操作使用者授權資訊,則不需要手動執行 flush privileges 語句,反之則需要。

相關文章