MySQL 使用者與權限管理 – CREATE USER / DROP USER
簡介
在 MySQL 中,使用者(user)是資料庫存取的最小單位。只有正確建立、管理使用者,才能確保資料庫的安全性與可維護性。CREATE USER 與 DROP USER 是兩個最基礎、最常使用的指令,它們負責新增與移除資料庫帳號。即使你只需要執行簡單的查詢或是開發測試環境,妥善管理使用者仍是不可或缺的步驟。
本篇文章將從概念說明、實作範例、常見陷阱與最佳實踐,帶你一步步掌握 MySQL 使用者的建立與刪除,並提供實務應用情境,讓你能在真實專案中安全、有效地操作 MySQL 使用者。
核心概念
1. 為什麼不直接使用 GRANT 建立使用者?
在 MySQL 5.7 之後,GRANT 仍可同時建立使用者,但官方已建議改用 CREATE USER + GRANT 的兩段式流程,主要原因有:
| 目的 | GRANT 直接建立使用者 |
CREATE USER + GRANT |
|---|---|---|
| 清晰度 | 一行指令即完成,易混淆「建立」與「授權」的邏輯 | 分開兩步,讓「建立帳號」與「授權」概念更分明 |
| 安全性 | 若忘記加上 IDENTIFIED BY,可能產生空密碼帳號 |
CREATE USER 必須明確指定密碼或認證方式 |
| 兼容性 | 某些 MySQL 版本的 GRANT 行為略有差異 |
CREATE USER 為標準化指令,跨版本行為一致 |
建議:在正式環境或自動化腳本中,始終使用
CREATE USER先建立帳號,再使用GRANT授權。
2. CREATE USER 的基本語法
CREATE USER '使用者名稱'@'主機' IDENTIFIED BY '密碼';
'使用者名稱':MySQL 帳號,大小寫視lower_case_table_names設定而定。'主機':允許從哪個主機連線。常見的寫法:'localhost':只能從本機連線。'%':允許任意 IP(不建議在正式環境使用)。'192.168.1.%':只允許特定網段。
IDENTIFIED BY:指定明文密碼,MySQL 會自動以雜湊方式儲存。IF NOT EXISTS:可避免重複建立時拋出錯誤。
3. DROP USER 的基本語法
DROP USER '使用者名稱'@'主機';
- 同樣支援
IF EXISTS,避免因使用者不存在而產生錯誤。 - 刪除使用者時,所有與之關聯的權限(GRANT)會同時被移除。
4. 認證方式的變化
從 MySQL 8.0 起,預設的認證插件改為 caching_sha2_password,若舊版客戶端不支援,可能需要改用 mysql_native_password:
CREATE USER 'old_client'@'%' IDENTIFIED WITH mysql_native_password BY 'MyPass123!';
程式碼範例
以下示範在 MySQL 8.0 環境下,從最簡單的建立使用者到較進階的情境設定。所有範例均已加入 註解,方便理解每一步的目的。
範例 1:建立本機測試帳號
-- 建立一個只能在本機使用的測試帳號 test_user,密碼為 TestPass123
CREATE USER IF NOT EXISTS 'test_user'@'localhost' IDENTIFIED BY 'TestPass123';
說明:使用
IF NOT EXISTS可避免重複執行腳本時產生錯誤。
範例 2:建立允許特定 IP 段的遠端帳號
-- 允許 192.168.10.* 網段的開發者使用 dev_user,密碼使用較長的隨機字串
CREATE USER 'dev_user'@'192.168.10.%' IDENTIFIED BY 'a9$K8mLz!Qp2#xV7';
技巧:使用
%通配符限制 IP 範圍,比直接使用'%'更安全。
範例 3:使用 caching_sha2_password(MySQL 8.0 預設)
-- 明確指定使用 caching_sha2_password 插件,適合新版客戶端
CREATE USER 'new_user'@'%' IDENTIFIED WITH caching_sha2_password BY 'Strong!Pass2025';
範例 4:兼容舊版客戶端的 mysql_native_password
-- 若應用程式仍使用舊版 MySQL Connector,必須改為 mysql_native_password
CREATE USER 'legacy_app'@'10.0.0.%' IDENTIFIED WITH mysql_native_password BY 'Legacy#2024';
範例 5:刪除使用者(帶 IF EXISTS)
-- 移除不再需要的臨時帳號 temp_user
DROP USER IF EXISTS 'temp_user'@'localhost';
範例 6:一次建立多個使用者
-- 同時建立兩個帳號,分別對應不同主機
CREATE USER
'report_user'@'10.1.2.3' IDENTIFIED BY 'Rpt#2025!',
'audit_user'@'10.1.2.%' IDENTIFIED BY 'Aud!t2025$';
注意:一次建立多個使用者可減少重複的
CREATE USER語句,提升腳本可讀性。
常見陷阱與最佳實踐
| 陷阱 | 可能的後果 | 解決方案或最佳實踐 |
|---|---|---|
使用 '%' 作為主機 |
任意 IP 均可嘗試連線,增加被暴力破解的風險。 | 限制 IP 範圍(如 192.168.1.%)或僅允許 localhost。 |
未加 IF NOT EXISTS |
重複執行部署腳本時會因使用者已存在拋出錯誤,導致部署中斷。 | 在自動化腳本中加入 IF NOT EXISTS(或 IF EXISTS)。 |
| 忘記設定密碼 | 產生空密碼帳號,任何人都能直接登入資料庫。 | 永遠使用 IDENTIFIED BY 或指定認證插件;避免使用 IDENTIFIED WITH auth_socket 除非明確需求。 |
| 使用過於簡單的密碼 | 容易被字典攻擊。 | 密碼至少 12 位、包含大小寫、數字與特殊字元,或使用密碼管理工具產生隨機密碼。 |
| 刪除使用者前未備份權限 | 失去授權資訊,未來若需復原會很麻煩。 | 使用 SHOW GRANTS FOR 'user'@'host'; 先備份授權腳本。 |
| 忽略認證插件差異 | 客戶端連線失敗(尤其在 MySQL 8.0 與舊版驅動混用時)。 | 明確指定 IDENTIFIED WITH <plugin>,或升級客戶端驅動。 |
| 忘記刷新權限 | 新增/刪除使用者後仍看到舊的權限表現。 | MySQL 5.7+ 自動刷新;若使用 FLUSH PRIVILEGES; 亦可確保即時生效。 |
推薦的安全流程
- 規劃使用者命名與主機範圍:統一命名規則(如
app_<module>)與 IP 限制。 - 產生強密碼:使用
openssl rand -base64 16或密碼管理器。 - 建立使用者:
CREATE USER IF NOT EXISTS ...。 - 授權:使用
GRANT或ROLE(MySQL 8.0+)分配最小權限。 - 測試連線:在開發機或測試環境驗證帳號可正確登入、權限符合預期。
- 紀錄變更:將
CREATE USER/DROP USER以及GRANT指令寫入版本控制(Git)或變更管理系統。
實際應用場景
1. 多租戶 SaaS 平台
在 SaaS 系統中,每個客戶(租戶)會擁有自己的資料庫或 schema。為了讓每個租戶只能存取自己的資料,常會:
- 為每個租戶建立 專屬的 MySQL 使用者(例如
tenant_001_user@%)。 - 限制該使用者只能在特定 schema 上執行
SELECT/INSERT/UPDATE/DELETE。 - 當租戶取消服務時,使用
DROP USER立即撤銷存取權,確保資料安全。
CREATE USER 'tenant_001_user'@'%' IDENTIFIED BY 'T1$Secure!';
GRANT SELECT, INSERT, UPDATE, DELETE ON tenant_001_db.* TO 'tenant_001_user'@'%';
2. CI/CD 自動化測試環境
在持續整合(CI)流程中,測試腳本常需要臨時資料庫帳號:
- 建立臨時使用者:測試開始前
CREATE USER,測試結束後DROP USER。 - 這樣可以避免測試程式直接使用
root,降低意外破壞正式資料的風險。
-- CI pipeline 前置步驟
CREATE USER 'ci_test_user'@'127.0.0.1' IDENTIFIED BY 'CiPass#2025';
GRANT ALL PRIVILEGES ON test_db.* TO 'ci_test_user'@'127.0.0.1';
3. 運維人員分層管理
大型企業往往有多層級的 DB 管理員:
- 只讀帳號:僅能查詢資料,供監控工具或報表使用。
- 開發帳號:可在開發環境執行 DML,但無法變更結構。
- 管理員帳號:具備
CREATE USER、DROP USER、GRANT等高階權限。
CREATE USER 'readonly_report'@'10.0.5.%' IDENTIFIED BY 'RptRead#2025';
GRANT SELECT ON prod_db.* TO 'readonly_report'@'10.0.5.%';
總結
CREATE USER與DROP USER是 MySQL 使用者管理的核心指令,分離建立與授權的做法更安全、易維護。- 正確指定 使用者名稱、主機、密碼或認證插件,並配合
IF NOT EXISTS/IF EXISTS,可以讓腳本在自動化部署中更具韌性。 - 常見的陷阱包括過度寬鬆的主機限制、弱密碼、忘記備份授權等,遵守最佳實踐(最小權限、密碼政策、變更紀錄)能大幅降低風險。
- 在多租戶 SaaS、CI/CD 測試、運維分層等實務情境中,透過精準的使用者與權限管理,不僅提升系統安全,也方便日後的維護與審計。
掌握了 CREATE USER / DROP USER 的使用方式,你就能在 MySQL 中建立一套可控、可審計且安全的使用者管理機制,為資料庫的長期健康奠定堅實基礎。祝你在 MySQL 的旅程中順利前行!