You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server只读故障转移数据库执行CLR函数遇System.IO.FileLoadException求助

问题描述

我们已在主数据库启用CLR,同步的只读故障转移数据库执行以下配置脚本后主库运行正常:

IF EXISTS (SELECT * FROM sys.database_principals WHERE name = 'CLR_Login')
BEGIN
    DROP USER CLR_Login;
END

CREATE USER CLR_Login FOR LOGIN CLR_Login
GO

DROP FUNCTION IF EXISTS [dbo].[EncryptData]
GO

DROP FUNCTION IF EXISTS [dbo].[DecryptData]
GO

IF EXISTS (SELECT name FROM sys.assemblies WHERE name = 'CryptoClr')
   DROP ASSEMBLY CryptoClr
GO

CREATE ASSEMBLY CryptoClr FROM 'C:\CLR\CryptoClr.dll' WITH PERMISSION_SET = UNSAFE
GO

CREATE FUNCTION EncryptData (@clearData NVARCHAR(MAX)) RETURNS NVARCHAR(MAX)
AS EXTERNAL NAME CryptoClr.UserDefinedFunctions.EncryptData
GO

CREATE FUNCTION DecryptData (@encryptedData NVARCHAR(MAX)) RETURNS NVARCHAR(MAX)
AS EXTERNAL NAME CryptoClr.UserDefinedFunctions.DecryptData
GO

SELECT dbo.DecryptData('sdfasdf/asdfasd/aadsf444f4') as 'Decrypted from CLR'
select dbo.EncryptData('4435345345345')

但在只读数据库中执行DecryptData或EncryptData函数时,出现System.IO.FileLoadException,请问是否需要在只读数据库上启用特定配置才能使用该功能?


解决方案

出现System.IO.FileLoadException通常和只读数据库的CLR程序集加载权限、实例级配置或数据库信任设置有关,按以下步骤排查配置:

  • 确认只读数据库所在SQL Server实例已启用CLR
    主库启用CLR不代表故障转移实例也已启用,执行以下语句检查并启用(需实例级权限):

    -- 检查CLR启用状态
    SELECT name, value_in_use FROM sys.configurations WHERE name = 'clr enabled';
    
    -- 若未启用,执行以下命令(需重启实例生效)
    EXEC sp_configure 'clr enabled', 1;
    RECONFIGURE;
    
  • 启用只读数据库的TRUSTWORTHY属性
    由于你的程序集使用PERMISSION_SET = UNSAFE,需要数据库被标记为可信才能加载。即使数据库是只读的,仍可设置该属性(设置后数据库保持只读状态):

    ALTER DATABASE [你的只读数据库名] SET TRUSTWORTHY ON;
    
  • 确认CLR程序集的权限映射正确
    只读数据库中,CLR_Login用户需拥有函数执行权限,同时登录名CLR_Login需具备实例级的UNSAFE ASSEMBLY权限(对应UNSAFE权限集的程序集):

    -- 给用户授予函数执行权限
    GRANT EXECUTE ON [dbo].[EncryptData] TO CLR_Login;
    GRANT EXECUTE ON [dbo].[DecryptData] TO CLR_Login;
    
    -- 给登录名授予UNSAFE权限
    USE master;
    GRANT UNSAFE ASSEMBLY TO CLR_Login;
    
  • 验证程序集是否完整同步到只读库
    检查只读数据库中是否存在CryptoClr程序集:

    SELECT name, permission_set_desc FROM sys.assemblies WHERE name = 'CryptoClr';
    

    若不存在,需确认数据库同步机制(如Always On)是否包含程序集对象,必要时可临时将只读库切换为读写模式,同步程序集后再切回只读状态。

  • 检查文件系统权限(针对依赖外部文件的场景)
    若CLR程序集依赖外部文件(如CryptoClr.dll本身),需确保只读数据库所在服务器的C:\CLR\路径存在该文件,且SQL Server服务账户拥有读取权限。不过SQL Server通常会将程序集二进制存储在数据库中,此情况较少见,但仍需排查。

内容的提问来源于stack exchange,提问作者Jed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:54:51