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

