.net - SQL Server 停止加载程序集

标签 .net sql-server logging sql-server-2008-r2 sqlclr

我们为 SQL Server 2008 R2 开发了一个程序集。

大会已经工作一周了。程序集中的托管存储过程整整一周都工作正常,然后就停止工作了。我们已经多次看到这个问题了。让它再次工作的方法是重新启动SQL Server。

Msg 10314, Level 16, State 11, Line 4
An error occurred in the Microsoft .NET Framework while trying to load assembly id 65536. The server may be running out of resources, or the assembly may not be trusted with PERMISSION_SET = EXTERNAL_ACCESS or UNSAFE. Run the query again, or check documentation to see how to solve the assembly trust issues. For more information about this error: 
  System.IO.FileLoadException: Could not load file or assembly 'myAssembly, Version=2.0.0.490, Culture=neutral, PublicKeyToken=5963130873dd3a75' or one of its dependencies. Exception from HRESULT: 0x80FC0E21 System.IO.FileLoadException:
  at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
  at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
  at System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
  at System.Reflection.Assembly.Load(String assemblyString)

我在网上找到了不同的文章。

This KB建议我可能从另一个 SQL Server 恢复了数据库,但我发誓我没有。

This blog说如果我在 SQL Server 2005 上安装 .NET 3.5,但我的是 SQL Server 2008 R2,并且出现此问题时我没有安装任何东西,我可能会遇到此问题。

最主要的是它可以持续一段时间。它只是随机停止工作。然后,如果我们重新启动 SQL Server,它将再次开始工作。我曾以为我的服务器确实内存不足,但现在,我又看到了这个问题。 SQL Server 仅使用 300MB RAM,而我的服务器有 16GB RAM。这听起来不可能,因为我的内存不足。

现在,我想收集有关此问题的更多信息。我可以打开并查看任何日志吗?欢迎任何有助于解决此问题的建议。

我运行了一些 SQL 查询。

SELECT * from sys.dm_clr_properties
=============================================
directory   C:\Windows\Microsoft.NET\Framework64\v2.0.50727\
version v2.0.50727
state   CLR is initialized

.

SELECT * from sys.dm_clr_appdomains
======================================================
0x0000000087160240  3   mydatabase.dbo[runtime].2   2011-08-12 08:44:08.940 10  1   E_APPDOMAIN_SHARED  1   1

.

SELECT * from sys.dm_clr_tasks
======================================================
0x000000008185A080  0x00000000818562C8  0x0000000000000000  E_TASK_ATTACHED_TO_CLR  E_ABORT_NONE    E_TYPE_ADUNLOAD 0   0
0x00000000818CE080  0x00000000818CA2C8  0x0000000000000000  E_TASK_ATTACHED_TO_CLR  E_ABORT_NONE    E_TYPE_FINALIZER    0   0
0x0000000081AD4C30  0x000000000400D048  0x0000000000000000  E_TASK_ATTACHED_TO_CLR  E_ABORT_NONE    E_TYPE_USER 0   0

.

SELECT * from sys.dm_clr_loaded_assemblies
<returns nothing>

* 更新 *

在我的 SQL Server 上,我创建了四个数据库。它们每个都附有相同的组件。现在,SQL Server 拒绝加载程序集并给出了上述错误。

SELECT * from sys.dm_clr_appdomains 显示当时只加载了一个应用程序域,而 SELECT * from sys.dm_clr_loaded_assemblies 显示根本没有加载任何程序集.

然后,我在其他三个数据库上运行相同的存储过程。它工作并成功加载程序集并成功运行存储过程。执行存储过程后。 SELECT * from sys.dm_clr_appdomains 现在显示只加载了四个应用程序域,SELECT * from sys.dm_clr_loaded_assemblies 显示现在加载了三个程序集。

这是有道理的。现在,我希望如果我在原始数据库中再次运行存储过程,它应该按原样加载程序集。你猜怎么了。不,事实并非如此。它仍然给我同样的错误。看起来这个数据库完全卡住了。修复此问题的唯一方法是重新启动 SQL Server。我希望系统表中的某处有一个标志/锁来支持这一点。我找不到它。欢迎任何想法。

现在,我的 SQL Server 处于需要我重新启动才能使其再次工作的状态。

* 更新 (8/31/2011) *

听起来好像和数据库的数据库所有者有关。这有点复杂。我们有两个站点和两个 AD 森林。 SQL Server 计算机已加入林 A,但数据库所有者来自林 B。林 A 和林 B 之间的连接不太稳定,因为它们位于通过 WAN 物理连接的两个不同站点。

一旦我将数据库所有者更改为 SQL 登录(非 Windows 帐户),我的存储过程到目前为止将运行几周,没有中断。

如果有人能解释一下,我会接受答案。

最佳答案

具有 EXTERNAL_ACCESS 的程序集通过一些复杂的路径落入 EXECUTE AS 路径下。当“dbo”无法映射到有效登录名时,就会出现此问题。 dbo 的登录名是 SID 为 sys.databases 中的 owner_sid 值的登录名。除非在 CREATE DATABASE 中使用了 AUTHORIZATION 子句,否则owner_sid 是发出 CREATE DATABASE 语句的主体的登录 sid。大多数情况下,这是登录并发出 CREATE DATABASE 的用户的 Windows SID。有了这些知识,我们就可以很容易地预见到可能出现的问题:

  • 复制数据库:A 本地用户(即 MachineA\userDomainA\user)在计算机 A 上发出 CREATE DATABASE,然后将数据库复制到机器 B(通过备份/恢复或通过文件复制)。 owner_sid 通过文件复制以及备份/恢复来保留,这在机器 B 上owner_sid 无效。所有需要 EXECUTE As 的操作都会失败,包括从数据库加载程序集。
  • 已删除的帐户。 CREATE DATABASE 是由已离开公司的用户发出的。 AD 帐户被删除,EXECUTE AS 突然神秘失败,包括加载程序集。
  • 笔记本电脑已断开连接。当笔记本电脑连接到工作网络时,创建数据库会出现问题。在家里,您可以使用 Windows 缓存的凭据登录,但 EXECUTE AS 想要连接到不可用的 AD 并且失败。加载程序集也会失败。第二天上类时,当你再次陷入 AD 状态时,问题就会神秘地自行解决。
  • AD 连接不稳定。 EXECUTE AS 不使用系统缓存的凭据,并且每次都会连接到 AD。如果 AD 连接存在问题(超时、错误),这些问题会在 EXECUTE AS 中表现为类似的超时和错误,包括加载程序集

所有这些问题都可以通过简单地在问题数据库的上下文中运行:EXECUTE AS USER = 'dbo';来诊断。如果它因错误而失败,则程序集加载问题的原因是 dbo 的 EXECUTE AS 上下文。

解决方案很简单,只需强制 owner_sid 进行有效登录即可。 sa 通常是最佳候选者:

ALTER AUTHORIZATION ON DATABASE::[<dbanme>] TO sa;

有趣的是,数据库可能看起来非常健康;表可用,您可以运行选择、更新、删除、创建和删除表等。只有某些组件需要 EXECUTE AS:

  • 代码签名要求代码具有 EXECUTE AS 子句
  • 装配验证
  • 在 T-SQL 代码中显式执行 EXECUTE AS
  • Service Broker 消息传送(包括查询通知)

后者是最常见的罪魁祸首,因为应用程序依赖 SqlDependency突然间似乎停止工作,或者出现随机问题。本文解释了 SqlDependency 最终如何依赖于 EXECUTE AS: The Mysterious Notification

关于.net - SQL Server 停止加载程序集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7034969/

相关文章:

c# - 啊!如何在初始化时正确更新 ComboBox 的 SelectedValue?

c# - 在类似 eBay 的系统中使用的最佳搜索引擎 (.NET)

.net - 为什么构造的委托(delegate)类的调用方法是虚拟的?

sql - Cursor ..Ques column Data as Column names and resp. 下的相关答案数据。问题专栏

logging - ArangoDB FOXX 日志记录 : how to

c# - 如何在 C# 中制作这种类型的选择文件夹对话框?

sql - 在SQL Server中创建临时表是否需要使用#?

sql-server - 自动将新数据从 MS Access 数据库导入 SQL Server

java - Logback:选择性屏蔽语句和谨慎模式

python - 记录器创建多个文件