SQL Server的WITH ENCRYPTION仅防普通用户直查,DBA、备份提取、内存dump、执行计划缓存等仍可还原明文;MySQL不支持该语法,始终明文可见;PG需用SECURITY DEFINER+视图封装逻辑,三者均非真正源码加密。

SQL Server 的 WITH ENCRYPTION 不是加密,只是防普通用户直查;MySQL 根本不支持该语法;PostgreSQL 需靠 SECURITY DEFINER + 视图封装——三者都做不到真正“源码加密”,只能控制谁能看到、在哪看到。
SQL Server 用 WITH ENCRYPTION 后还能被看到吗
能。它只让 sp_helptext 和 sys.sql_modules.definition 返回空或乱码,但以下情况仍可还原明文:
- DBA 或拥有
VIEW SERVER STATE权限的人,可通过查询执行计划缓存(sys.dm_exec_query_plan)提取原始文本 - 启用专用管理员连接(DAC)后,直接读取内存页或系统表原始数据块
- 从数据库备份文件中提取
sys.sysobjvalues表内容并解密(SQL Server 内部使用动态密钥,首次执行时解密到内存) - 第三方工具如 SQL Prompt(7.0+)在预览对象时会自动显示明文,无需额外操作
另外,加密后无法用 ALTER PROCEDURE 修改,必须先 DROP 再 CREATE,线上误删风险陡增。
MySQL 存储过程根本不能加 WITH ENCRYPTION
该关键字在 MySQL 中是无效语法:不报错、不生效、也不提示,只默默忽略。所有存储过程源码始终暴露在以下位置:
SHOW CREATE PROCEDURE p_nameSELECT ROUTINE_DEFINITION FROM information_schema.ROUTINES WHERE ROUTINE_NAME = 'p_name'-
SELECT body FROM mysql.proc WHERE name = 'p_name'(只要账号有SELECT权限)
常见错误是把 SQL Server 写法直接复制进 MySQL,以为加了就安全了。真正可行的只有权限隔离:
REVOKE SHOW ROUTINE ON *.* FROM 'app_user'@'%'REVOKE SELECT ON information_schema.ROUTINES FROM 'app_user'@'%'REVOKE SELECT ON mysql.proc FROM 'app_user'@'%'- 仅授予
EXECUTE权限:GRANT EXECUTE ON PROCEDURE db.p_name TO 'app_user'@'%'
PostgreSQL 怎么隐藏 pg_proc.prosrc
PG 没有原生加密选项,但可通过组合机制限制调用者视角:
- 创建
SECURITY DEFINER函数,其执行权限以函数所有者身份进行,调用者无法查pg_proc.prosrc - 再用视图包装该函数结果,对外只暴露字段,不暴露逻辑来源
- 禁用
pg_read_all_data等高权限角色给普通用户
注意:超级用户仍可直接查 pg_proc,且若函数内含 RAISE NOTICE 或日志输出,可能泄露线索。混淆变量名、拼接字符串等手段对 PG 无实质防护作用,只是徒增维护成本。
别碰“运行时解密执行”这种想法
网上流传的用 AES_ENCRYPT() 或 Base64 加密整个过程体、再用 PREPARE/EXECUTE 动态还原执行——这在任何主流 SQL 引擎中都不可行:
- SQL Server 不支持将加密字符串解密后作为 T-SQL 执行(
sp_executesql只接受明文字符串) - MySQL 的
PREPARE要求输入为字面量或变量,但变量内容无法在运行时“解密并重编译成新存储过程” - PostgreSQL 的
EXECUTE也不能执行加密后的函数体字符串
所谓“加固”,本质是权限边界和逻辑分层问题:敏感计算前移到应用层(Python/Java),数据库只做原子读写;硬编码密钥比“加密过程”更危险,且更容易被忽略。

















