存储过程与权限管理
在 seekdb 中,PL 权限用于管理用户对存储过程和存储函数的 操作。存储过程是数据库中的一种例程,可以通过 CREATE PROCEDURE 和 CREATE FUNCTION 语句创建,并可在创建时指定其所属的数据库。执行存储过程时使用 CALL 语句,而存储函数则在表达式中直接引用,并在计算表达式时返回一个值。
存储过程创建与权限
seekdb 权限体系与存储过程的关系如下:
| 权限 | 描述 |
|---|---|
| CREATE ROUTINE | 可创建 PROCEDURE 和 FUNCTION 的权限。 |
| EXECUTE | 可执行 PROCEDURE 和 FUNCTION 的权限。 |
| ALTER ROUTINE | 可修改和删除 PROCEDURE 和 FUNCTION 的权限。 |
-
创建存储过程需要拥有
CREATE ROUTINE权限。在授予CREATE ROUTINE权限后,用户可以创建PROCEDURE。 -
在创建完
PROCEDURE之后,系统会自动为创建的PROCEDURE添加对应的EXECUTE和ALTER ROUTINE权限。
示例如下:
GRANT CREATE ROUTINE ON my.* TO mingye;
CREATE PROCEDURE p1()
-> BEGIN
-> SELECT 1 FROM dual;
-> END;
-> /
返回结果如下:
+---------------------------------------------------------------------+
| Grants for mingye@% |
+---------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `mingye`@`%` |
| GRANT CREATE ROUTINE ON `my`.* TO `mingye`@`%` |
| GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE `my`.`p1` TO `mingye`@`%` |
+---------------------------------------------------------------------+
automatic_sp_privileges 系统变量
如果 automatic_sp_privileges 系统变量默认为 1,则系统自动创建 EXECUTE 和 ALTER ROUTINE 权限。如果你不需要这个权限,你可以手动删除这个权限。
示例如下:
SELECT @@automatic_sp_privileges;
+---------------------------+
| @@automatic_sp_privileges |
+---------------------------+
| 1 |
+---------------------------+
1 row in set (0.03 sec)
查询到 automatic_sp_privileges 系统为 1,现在可以手动删除这个自动创建的权限。
REVOKE EXECUTE ON PROCEDURE my.p1 FROM mingye;
CALL p1();/
automatic_sp_privileges 是全局变量,需要 SUPER 权限才能修改。示例如下:
SET GLOBAL automatic_sp_privileges = 0;
ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER privilege(s) for this operation
DEFINER 与 SECURITY TYPE
在创建 PROCEDURE 时可以指定 DEFINER。如果定义时忽略了 DEFINER,那么 DEFINER 会默认设为创建该 PROCEDURE 的用户。
CREATE DEFINER = 'admin'@'localhost' PROCEDURE p1()
BEGIN
UPDATE t1 SET counter = counter + 1;
END;
SHOW PROCEDURE STATUS LIKE '%p2%';
返回结果如下所示:
+------+------+-----------+-----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| Db | Name | Type | Definer |x| Security_type |
+------+------+-----------+-----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
| test | p2 | PROCEDURE | admin@localhost |x| DEFINER |
+------+------+-----------+-----------------+---------------------+---------------------+---------------+---------+----------------------+----------------------+--------------------+
指定 DEFINER 的用户:
- 拥有
SUPER权限的用户可以为DEFINER指定任何值。 - 否则,
DEFINER只能指定为当前用户,使用CURRENT_USER、CURRENT_USER(),或者直接写文本。
如果 DEFINER 指定了一个不存在的用户,将会创建一个孤儿对象(orphan object)。
在调用存储对象时,执行者需要具备以下权限:
- 调用者需要
EXECUTE权限。 DEFINER需要EXECUTE权限。
在存储对象执行期间,将根据 DEFINER 指定的用户的权限进行执行。
让一个存储对象变为孤儿对象
一个存储对象变为孤儿对象,即当你尝试删除一个用户时,如果该用户被定义为任何存储对象的 DEFINER,操作会因为存在依赖关系而失败。为了避免这种情况,系统可能要求先删除或修改这些存储对象,以便能够成功删除用户。
- DROP USER 时,如果用户是任意一个存储对象的
DEFINER,执行将失败并报错。 - RENAME USER 时,如果用户是任意一个存储对象的
DEFINER,执行将失败并报错。
如果数据库系统允许在没有相应的存储对象删除或修改的情况下删除用户,那么在删除用户之后,相关的存储对象将变成没有 DEFINER 的孤儿对象。