首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 預存程序執行權限深度解析:DEFINER 與 SQL SECURITY 機制

     編輯:MySQL 資料庫相關知識

MySQL 預存程序執行權限涉及調用者權限與定義者權限雙重檢查,且受 SQL SECURITY 特性 (DEFINER/INVOKER) 控制。本文通過完整實戰案例,深度剖析 EXECUTE、CREATE USER、GRANT OPTION 等權限交互邏輯,解決「權限明明給了卻報錯」的經典困惑。

核心概念

概念說明
DEFINER建立預存程序時指定的 'user'@'host',預設為建立者
SQL SECURITYDEFINER (預設) 以定義者權限執行;INVOKER 以調用者權限執行
權限檢查點1. 調用者需有程序 EXECUTE 權限
2. 執行時 (DEFINER 模式) 需有定義者在程序內每條 SQL 所需權限

實戰案例完整復盤

場景設定

  • 資料庫:configdb
  • 預存程序:sp_dev_test_user_add,DEFINER=`user_admin`@`%`,SQL SECURITY DEFINER (預設)
  • 程序內操作:建臨時表、查 mysql.user、動態建用戶、GRANT 權限、寫業務表
  • 調用用戶:user_test1@%

步驟 1:調用者缺 EXECUTE 權限

GRANT SELECT,INSERT,UPDATE,DELETE ON configdb.* TO 'user_test1'@'%';
-- 執行 CALL 報錯
ERROR 1370 (42000): execute command denied to user 'user_test1'@'%' for routine 'configdb.sp_dev_test_user_add'

修正: GRANT EXECUTE ON configdb.* TO 'user_test1'@'%';

步驟 2:DEFINER 用戶不存在

ERROR 1449 (HY000): The user specified as a definer ('user_admin'@'%') does not exist

修正: CREATE USER 'user_admin'@'%' IDENTIFIED BY 'pass';

步驟 3:DEFINER 缺 EXECUTE 權限

GRANT SELECT,INSERT,UPDATE,DELETE ON configdb.* TO 'user_admin'@'%';
-- 執行報錯
ERROR 1370 (42000): execute command denied to user 'user_admin'@'%' for routine 'configdb.sp_dev_test_user_add'

關鍵認知: DEFINER 同樣需要程序的 EXECUTE 權限 (DEFINER 模式下以定義者身份執行,故需定義者有 EXECUTE)。

修正: GRANT EXECUTE ON configdb.* TO 'user_admin'@'%';

步驟 4:DEFINER 缺業務操作權限 (建用戶、GRANT、建臨時表)

ERROR 1044 (42000): Access denied for user 'user_admin'@'%' to database 'configdb'

分析: 程序內含 CREATE USER、GRANT、CREATE TEMPORARY TABLES、寫 mysql.user 等操作,DEFINER 必須擁有對應權限。

修正 (逐步補齊):

-- 全域建用戶與授權權限 (需 WITH GRANT OPTION)
GRANT CREATE USER ON *.* TO 'user_admin'@'%' WITH GRANT OPTION;

-- 庫級臨時表、增刪改查、執行
GRANT SELECT,INSERT,UPDATE,DELETE,CREATE TEMPORARY TABLES,EXECUTE ON configdb.* TO 'user_admin'@'%';

-- mysql 系統庫權限 (程序查 mysql.user、mysql.proc、mysql.func)
GRANT SELECT,INSERT,UPDATE,DELETE ON mysql.* TO 'user_admin'@'%';

步驟 5:DEFINER 缺 mysql.user 表 SELECT 權限

ERROR 1142 (42000): SELECT command denied to user 'user_admin'@'%' for table 'user'

修正: 已包含在上一步 GRANT SELECT ... ON mysql.* 中。

最終結果

mysql> CALL sp_dev_test_user_add('uapp_yzz','172.16.%','yzz','yzz@email','MySQL DBA');
Query OK, 0 rows affected (0.05 sec)

權限矩陣總結

角色需求權限授權範例
調用者 (INVOKER)程序 EXECUTEGRANT EXECUTE ON db.* TO 'caller'@'%';
定義者 (DEFINER, SQL SECURITY DEFINER)程序 EXECUTE + 程序內每條 SQL 所需權限見上文分步授權
建立者 (CREATE ROUTINE)庫級 CREATE ROUTINEGRANT CREATE ROUTINE ON db.* TO 'dev'@'%';
修改者 (ALTER ROUTINE)庫級 ALTER ROUTINEGRANT ALTER ROUTINE ON db.* TO 'dev'@'%';

最佳實踐建議

  1. 優先使用 SQL SECURITY INVOKER: 建立程序時指定 CREATE PROCEDURE ... SQL SECURITY INVOKER,權限檢查僅針對調用者,避免 DEFINER 權限維護地獄。
  2. 若必須用 DEFINER: 建立專用 routine_executor@% 帳號,僅授予程序所需最小權限集,嚴禁使用 root/高權限帳號。
  3. 權限審計: 定期執行 SHOW GRANTS FOR 'definer'@'%'; 核對與程序邏輯一致性。
  4. 避免在程序內做 DDL/授權: 建用戶、GRANT 等運維操作移至應用層或管理腳本,程序專注業務邏輯。
  5. 版本注意: MySQL 8.0 引入 SET DEFINER 需 SET_USER_ID 權限,修改 DEFINER 更嚴格。

常見報錯對照表

錯誤碼訊息原因解決
1370execute command denied ... for routine調用者或 DEFINER 缺程序 EXECUTEGRANT EXECUTE ON db.* TO user
1449The user specified as a definer ... does not existDEFINER 帳號不存在CREATE USER definer
1044Access denied for user 'definer' to databaseDEFINER 缺庫級業務權限補授予對應庫權限
1142SELECT/INSERT/UPDATE command denied for tableDEFINER 缺具體表權限補授予表級權限

徹底理解 MySQL 預存程序的雙重權限模型,是資料庫開發進階的必修課。將權限設計視為架構一環,而非事後補丁,方能構建安全、可維護的資料庫應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved