除了重新启动 SQL Server,还有什么方法可以强制重置 SQLCLR AppDomain?

Jus*_*ing 11 sql-server sql-clr

我想强制重置 SQLCLR 使用的 AppDomain。除了重新启动 SQL Server 实例之外,我还能怎么做?

Sol*_*zky 8

有一个更优雅的解决方案,不会影响所有其他程序集:只需更改应用程序域中一个程序集的 PERMISSION_SET(应用程序域是每个用户)。

ALTER ASSEMBLY [AssemblyName] WITH PERMISSION_SET = {1 of the 2 levels that 
                                                      this assembly is not current at}
Run Code Online (Sandbox Code Playgroud)

请记住,您需要将 PERMISSION_SET 设置回原来的状态。此外,在更改 PERMISSION_SET 将卸载它之前,您需要访问程序集中的方法;更改当前未加载到活动应用程序域中的程序集,但使用另一个程序集,对应用程序域没有影响(应用程序域是每个数据库、每个用户,而不是每个程序集)。


UPDATE
上面描述的方法是最细粒度的方法,它只会卸载一个应用程序域。但是,它确实要求可以将程序集设置为其他两个级别之一。对于标记为SAFE只有在以下情况下才有可能的程序集

  • 数据库设置为TRUSTWORTHY ON,或
  • 程序集已签名,并且基于非对称密钥的登录存在,该密钥本身基于与程序集相同的签名,并且已被授予EXTERNAL ACCESS ASSEMBLYUNSAFE ASSEMBLY权限

在这种情况下,您可以简单地更改TRUSTWORTHY设置ON,然后立即OFF再次返回,这将卸载该特定数据库中的所有应用程序域:

ALTER DATABASE CURRENT SET TRUSTWORTHY ON;
ALTER DATABASE CURRENT SET TRUSTWORTHY OFF;
Run Code Online (Sandbox Code Playgroud)

如果无论如何您在数据库中只有一个应用程序域(我怀疑 95% 或更多的时间都是这种情况),那么这里描述的两种方法具有相同的净效果。在这种情况下,该ALTER DATABASE方法似乎更简单,因为它不需要指定特定的对象名称,也不需要知道原始对象PERMISSION_SET是什么。

此外,如果您只有一个应用程序域,那么ALTER DATABASE即使在数据库已设置为TRUSTWORTHY ON或您已使用适当权限设置密钥库登录的情况下,该方法也更简单。如果您使用的是基于密钥的登录,那么您可以设置TRUSTWORTHYON,然后OFF再如上所述。但是,如果您已经TRUSTWORTHY设置为ON,则只需将其反转并设置为OFF,然后立即返回ON

ALTER DATABASE CURRENT SET TRUSTWORTHY OFF;
ALTER DATABASE CURRENT SET TRUSTWORTHY ON;
Run Code Online (Sandbox Code Playgroud)


Han*_*non 6

我知道这有点残酷,但是禁用 CLR 并重新启用它呢?

sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'clr enabled', 0;
GO
RECONFIGURE;
GO
sp_configure 'clr enabled', 1;
GO
RECONFIGURE;
GO
Run Code Online (Sandbox Code Playgroud)

  • 关于此方法的一个重要细节是它在对 STANDBY(只读)数据库执行时有效;我尝试过的所有其他方法都没有。我需要这个是因为对 CLR 程序集的更新通过日志传送到 STANDBY 目录正常传播,但 AppDomain 没有重新加载——因此它继续运行来自旧版本 .dll 的代码大约一天。 (2认同)