我想使用我在 C# CLR 中开发的代码用于系统上的所有数据库,这样我就不必将每个数据库设置为可信任并打开 CLR 并在每个数据库中保留一堆相同的代码.
从管理和安全的角度来看,有没有最好的方法来做到这一点?CLR 函数非常基本,如字符串中断器、电子邮件验证、url en/decode、base64 等。我希望每个数据库中只有 dbo 模式能够访问这些函数。
- 有什么简单的方法可以做到这一点吗?
- 此外,我不清楚 CLR dll 是否已嵌入,如果我移动数据库,它会标记,还是我也必须移动 dll。
谢谢
在我们公司,我们有精确的设置。当您创建 CLR 程序集时,该程序集的二进制表示形式存储在您创建它的数据库中。如果您在任何时间点移动数据库,这使您可以随身携带它(甚至编写脚本)。
几个月前,我们的数据中心被水淹没了——几台服务器被水淹没了。当我重建它们时,我只使用了前一天晚上备份的数据库。到目前为止我们没有遇到任何问题..(摸木头!)
我不确定从安全角度来看这是否正确,但我们授予对 CLR 过程等的访问权限的方式是在共享数据库中创建一个角色,然后将来自其他数据库的用户添加到该角色。然后授予该角色在 CLR proc 上执行。
如果 CLR 试图执行诸如访问它所包含的数据库之外的资源之类的操作,则可能会出现访问问题,但您可以在创建程序集时设置程序集的权限。下面的链接提供了比我在这里无法解释的更多关于权限的信息:
http://msdn.microsoft.com/en-us/library/ms345101.aspx
我希望这对你有帮助。
程序集二进制文件作为 blob 存储在数据库中,因此无论数据库走到哪里,它都会随身携带。CLR 仅在实例上启用——没有针对该实例的特定于数据库的设置。
无论如何,你为什么要这样做?
(我不是要争论;我只是想听听所涉及的动机,因为也许可以用满足您需要的不同方式解决问题。)
除了将程序集放在共享数据库中之外,没有办法轻松地做到这一点。
也就是说,我认为采用以数据库为中心的架构是有利的,除非存在有非常令人信服的集中化理由的特定情况。原因是将程序集(或与此相关的任何东西)放在数据库之外会在您的环境中产生依赖性。这恰恰是微软从 SQL Server 2012 开始构建包含数据库的相反方法。
当您开始需要使用复制或集群等功能时,这种依赖性可能会极大地增加部署的复杂性,同时也会增加故障排除和故障转移过程。
对于不熟悉该系统的人来说,这种体系结构不太明显(即,它不太容易自我发现,也不太容易自我记录)。
如果您最终需要在不同的数据库中使用不同的安全性,或者任何涉及变化的事情,您就会陷入困境。
如果将这些数据库部署给客户(听起来他们不会,但为了完整起见我会这么说),这会增加部署过程、维护和故障排除的复杂性。
由于所有数据库都会共享此代码,如果引入(或修复!)任何错误,这可能会破坏所有依赖数据库的应用程序。全面的单元测试绝对是必须的。
如果您有多个需要相同功能的数据库,还有其他方法可以减少涉及的重复数量,我认为这就是练习的重点。与数据库本身中的数据相比,即使是一个相当复杂的 CLR 程序集也不会占用太多物理存储空间(几乎总是如此),所以我不认为这是一个有效的论点,除非你有成千上万的微型数据库需要这个部件。
您可以做的是修改这些数据库部署过程的其他部分,以减少源重复。例如,从源代码管理中 CLR 代码的公共位置构建和部署程序集。或者,创建一个将相同程序集部署到数据库的脚本。这部分东西尽量自动化,不会有什么大不了的。
我同意我的建议是权衡,因为仍然会有一些重复,但这必须与实施不遵循规定标准的架构所涉及的负面因素相平衡。只有您可以决定什么适合您的环境。
正如其他两个答案正确指出的那样,程序集被加载到特定的数据库中并且不是系统范围的(尽管我相当确定该
assembly_id
值在系统范围内是唯一的)。这意味着它们会随着它们加载到的每个数据库进行备份和恢复。此外,(via )的
enabled
/disabled
设置是系统范围的。作为旁注,该设置仅适用于用户创建的CLR 功能;一般意义上的 CLR 始终处于启用状态,因为某些内置功能依赖于它。CLR Integration
sp_configure
也就是说,虽然这里的其他两个答案确实提出了有效的观点,但这些观点并不是特定于 SQLCLR 的,并且没有提及做出此决定时特定于 SQLCLR 代码的因素。如果您将代码部署到每个单独的数据库(假设您有许多数据库)、潜在的资源争用问题、潜在的安全相关问题等,则需要考虑内存问题。
我已经提供了在集中式数据库与单独数据库部署之间做出决定时应该牢记的全面列表,特别是对于 SQLCLR 代码。不要在此处复制列表,请参阅以下答案(也在 DBA.SE 上):
如何从性能的角度更好地使用 CLR Function(在每个 DB 中重复或具有通用功能)?
此外,在相关说明中,我会质疑为什么将任何数据库设置为
TRUSTWORTHY ON
. 问题中提到的功能(即“字符串中断器、电子邮件验证、url en/decode、base64 等”)在SAFE
程序集中都是可能的。除非绝对必要,否则不应使用 theEXTERNAL_ACCESS
或UNSAFE
perission_set 值。如果某些函数需要它,那么这些函数应该放在一个单独的程序集中,该程序集只包含SAFE
代码,这样任何不进行数据访问并被标记为的标量函数都IsDeterministic = true
可以利用被标记的性能优势能够参与并行计划。