MySQL 使用者與權限管理:GRANT / REVOKE 完全攻略
簡介
在企業級的資料庫環境中,安全性與可維護性往往是系統能否穩定運作的關鍵。MySQL 透過 使用者(User)與 權限(Privilege)機制,讓管理者可以細緻地控制誰能對哪個資料庫、哪張資料表、甚至是哪條 SQL 語句執行操作。
本篇文章聚焦在兩個最常使用的指令——GRANT 與 REVOKE,說明它們的語法、使用情境與最佳實務,幫助你從入門到中階的權限管理需求,都能得心應手。
核心概念
1. 權限的基本類型
MySQL 的權限大致可分為 全域、資料庫、資料表、欄位 與 例程(PROCEDURE/FUNCTION) 五層。
- 全域權限(
ON *.*)會影響所有資料庫與資料表,常見於SUPER、FILE等高階權限。 - 資料庫層級(
ON db_name.*)只授予指定資料庫內的所有物件。 - 資料表層級(
ON db_name.tbl_name)針對單一資料表。 - 欄位層級(
ON db_name.tbl_name (col1, col2))允許細部控制欄位的讀寫。
2. GRANT 的語法結構
GRANT priv_type [(column_list)] [, priv_type ...]
ON object_type
TO user_specification [, user_specification ...]
[WITH GRANT OPTION];
priv_type:欲授予的權限,如SELECT、INSERT、UPDATE、DELETE、EXECUTE等。object_type:權限的作用範圍,例如*.*(全域)或mydb.*(資料庫)等。user_specification:使用者與主機的組合,格式為'user'@'host'。WITH GRANT OPTION:允許被授權者再把同樣的權限授予其他使用者。
3. REVOKE 的語法結構
REVOKE priv_type [(column_list)] [, priv_type ...]
ON object_type
FROM user_specification [, user_specification ...];
REVOKE 會從指定使用者移除先前的權限,若同時撤銷 GRANT OPTION,則會限制其再授權的能力。
4. 權限變更的即時生效與刷新
MySQL 在執行 GRANT / REVOKE 後,會自動更新內部的權限快取(mysql.user、mysql.db 等表格),不需要手動執行 FLUSH PRIVILEGES。只有在直接修改權限表格時才需要 FLUSH PRIVILEGES。
程式碼範例
以下範例均以 root(或具備 GRANT OPTION 的管理者)身份執行,示範常見的授權與撤權情境。
範例 1:建立新使用者並授予全域讀寫權限
-- 建立使用者 alice,密碼使用 MySQL 8.0 內建的認證方式
CREATE USER 'alice'@'%' IDENTIFIED BY 'StrongP@ssw0rd';
-- 授予全域 SELECT、INSERT、UPDATE、DELETE 權限
GRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'alice'@'%';
說明:
%表示任意主機都可連線,實務上建議限制為公司內部的 IP 範圍,例如'alice'@'192.168.10.%'。
範例 2:僅授予特定資料庫的 SELECT 權限,並允許再授權
GRANT SELECT ON sales_db.* TO 'alice'@'%' WITH GRANT OPTION;
說明:
WITH GRANT OPTION讓alice可以把SELECT權限再授給其他使用者,常用於資料分析團隊的「只讀」帳號。
範例 3:欄位層級的授權(只允許讀取 email 欄位)
GRANT SELECT (email) ON hr_db.employees TO 'bob'@'localhost';
說明:此設定僅允許
bob讀取employees表的NULL。
範例 4:撤銷特定資料表的 UPDATE 權限
REVOKE UPDATE ON inventory.products FROM 'alice'@'%';
說明:即使
alice之前擁有全域的 UPDATE 權限,這條指令會在inventory.products表上移除它,使其只能執行SELECT、INSERT、DELETE。
範例 5:同時撤銷 GRANT OPTION 與所有權限
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'alice'@'%';
DROP USER IF EXISTS 'alice'@'%';
說明:先撤銷所有權限與授權能力,再刪除使用者帳號,確保不留下任何隱藏的權限。
常見陷阱與最佳實踐
| 陷阱 | 可能的後果 | 改善方式 |
|---|---|---|
使用 GRANT ALL 在全域 |
任何人都有最高權限,易成為資安漏洞。 | 僅授予必要的最小權限(最小權限原則)。 |
忘記加上主機限定 ('user'@'%') |
帳號可被任意 IP 暴力嘗試。 | 盡量使用具體的 IP 或子網 ('user'@'10.0.0.%')。 |
在 mysql.* 表直接編輯後未 FLUSH |
權限變更不會立即生效,造成測試困擾。 | 只使用 GRANT/REVOKE,或在手動編輯後執行 FLUSH PRIVILEGES。 |
撤銷權限時忘記 FROM |
語法錯誤,導致指令執行失敗。 | 確認使用 REVOKE ... FROM 的正確語法。 |
授權過度使用 WITH GRANT OPTION |
使用者自行擴散權限,增加管理成本。 | 僅在確實需要的情境下使用,並定期審核授權鏈。 |
最佳實踐
- 最小權限:先從最小的權限開始,逐步測試功能需求,再適度放寬。
- 角色(Role)概念:MySQL 8.0 以上支援角色(
CREATE ROLE),可將一組權限抽象成角色,再授予使用者,方便管理。 - 定期審計:使用
SELECT * FROM mysql.user;、mysql.db;等表格,或透過mysqlshow --privileges檢查權限分布。 - 密碼政策:配合
validate_password插件,強制使用者密碼符合複雜度要求。 - 日誌與監控:開啟
audit_log(或使用 MariaDB 的MariaDB Audit Plugin),即時偵測不尋常的授權變更。
實際應用場景
開發/測試環境的臨時帳號
- 使用
GRANT SELECT, INSERT, UPDATE, DELETE ON dev_db.* TO 'dev_user'@'10.0.1.%',並在測試結束後DROP USER 'dev_user'@'10.0.1.%';,防止帳號遺留。
- 使用
資料分析平台的只讀帳號
- 為 BI 團隊建立
analytics角色:CREATE ROLE 'analytics'; GRANT SELECT ON analytics_db.* TO 'analytics'; GRANT 'analytics' TO 'charlie'@'10.0.2.%'; - 只要撤銷角色,即可一次收回所有只讀權限。
- 為 BI 團隊建立
多租戶 SaaS 系統的資料隔離
- 為每個客戶建立獨立的資料庫與使用者:
CREATE DATABASE tenant_001; CREATE USER 'tenant001_user'@'%' IDENTIFIED BY 'Pwd123!'; GRANT ALL PRIVILEGES ON tenant_001.* TO 'tenant001_user'@'%'; - 透過
REVOKE ALL PRIVILEGES FROM 'tenant001_user'@'%'; DROP USER ...;快速關閉帳號。
- 為每個客戶建立獨立的資料庫與使用者:
自動化部署腳本
- 在 CI/CD pipeline 中加入授權腳本(使用
mysql -e "GRANT ..."),確保每次部署後環境權限保持一致。
- 在 CI/CD pipeline 中加入授權腳本(使用
總結
GRANT 與 REVOKE 是 MySQL 權限管理的核心工具,掌握其語法與層級概念,能讓你在 安全、可維護 與 彈性 之間取得最佳平衡。本文從概念說明、實作範例、常見陷阱到實務場景,提供了一條完整的學習路徑;配合 最小權限原則、角色化管理與定期審計,你的 MySQL 環境將更加堅固、易於運營。祝你在資料庫管理的道路上,越走越順!