SQL SECURITY INVOKER 模式下,MySQL在每条SQL语句执行前均以调用者身份校验其对涉及对象的权限,如SELECT需检查调用者是否有SELECT ON db.table,INSERT则检查INSERT权限,权限边界清晰、失败即时暴露、不依赖DEFINER账户状态。

SQL SECURITY INVOKER 是怎么校验权限的
它不切换执行身份,每条 SQL 语句运行前都检查当前连接用户(即调用者)是否具备对应对象的权限。比如 SELECT * FROM orders 这句,MySQL 就查调用者有没有 SELECT ON app_db.orders;如果过程里还有 INSERT INTO audit_log,就再查一次 INSERT ON app_db.audit_log。
这意味着:权限边界清晰、可审计、不依赖外部账户状态。只要给调用者授了该干的权限,过程就能跑;没授,就立刻报错,不会“悄悄越权”或“因 DEFINER 消失而突然崩掉”。
DEFINER 模式下最常踩的三个坑
- DEFINER 用户被删或 host 不匹配(如定义为
'admin'@'localhost',但应用连的是'admin'@'%'),过程直接报ERROR 1449: The user specified as a definer ('admin'@'localhost') does not exist - 跨环境部署时,目标库没有同名 DEFINER,或该用户没被授予过程内涉及的所有表权限,一调就
ERROR 1142 - 过程里读系统变量(如
@@max_connections)或访问performance_schema,MySQL 8.0+ 要求 DEFINER 有SYSTEM_VARIABLES_ADMIN等额外权限,否则静默失败
INVOKER 不是万能的,但它把问题暴露得更早
它不会掩盖权限缺失——比如视图 JOIN 了三张表,你只给调用者授了两张表的 SELECT 权限,第三张漏了,调用时就明确报 Table 'app_db.config' doesn't exist(实际存在,只是没权限)。这种“失败即反馈”的机制,反而让权限配置更可控。
但要注意:
- 必须显式写
SQL SECURITY INVOKER,不写就是默认DEFINER - 调用者需同时拥有过程本身(
EXECUTE ON PROCEDURE app_db.p_log)和所有内部操作对象的权限 - 若过程要执行
TRUNCATE或写入系统库,INVOKER 模式基本不可行,此时必须换回 DEFINER 并严格管控 owner 账户
什么时候该坚持用 INVOKER
当你的场景满足以下任意一条,就该强制用 SQL SECURITY INVOKER:
- 应用多租户,不同用户连接进来执行同一过程,且数据隔离靠行级/表级权限控制
- 使用自动化 DDL 工具(如 Liquibase、Flyway)管理 schema,避免工具误补
DEFINER导致行为漂移 - 安全合规要求“权限最小化”,审计项里明确要看到“谁在什么上下文里访问了什么”
- 过程只做读操作,且所有目标表都能统一授权给业务角色
真正容易被忽略的是 host 匹配精度和系统权限的隐性依赖——INVOKER 看似简单,但它把权限配置的责任彻底交还给了 DBA 和应用侧,一步漏授,就卡在调用那一刻,没法靠“定义者兜底”。


















