Dot-Net

SQL Server 停止載入程序集

  • August 12, 2011

我們為 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)

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

這個 KB表明我可能已經從另一個 SQL Server 恢復了數據庫,但我發誓我沒有這樣做。

這個部落格說如果我在 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當時向我展示了只載入了一個 appdomain,並SELECT * from sys.dm_clr_loaded_assemblies告訴我根本沒有載入任何程序集。

然後,我在其他三個數據庫上執行相同的儲存過程。它工作並成功載入了程序集並成功執行了儲存的過程。執行儲存過程後。 SELECT * from sys.dm_clr_appdomains現在顯示我只載入了四個 appdomain,並SELECT * from sys.dm_clr_loaded_assemblies顯示現在載入了三個程序集。

這是有道理的。現在,我希望如果我在原始數據庫中再次執行儲存過程,它應該能夠按原樣載入程序集。你猜怎麼了。不,它沒有。它仍然給我同樣的錯誤。看起來這個數據庫完全卡住了。修復它的唯一方法是重新啟動 SQL Server。我希望系統表中某處有一個標誌/鎖來支持它。我找不到它了。歡迎任何想法。

現在,我的 SQL Server 處於需要我重新啟動才能使其再次工作的狀態。

*** 更新(2011 年 8 月 31 日)***

聽起來它與數據庫的數據庫所有者有關。這有點複雜。我們有兩個站點和兩個 AD 森林。SQL Server 電腦已加入林 A,但數據庫所有者來自林 B。林 A 和林 B 之間的連接不是那麼穩定,因為它們位於通過 WAN 物理連接的兩個不同站點中。

一旦我將數據庫所有者更改為 SQL 登錄名(非 Windows 帳戶),我的儲存過程就已經執行了幾週,沒有中斷。

如果有人可以解釋,我會接受答案。

帶有 EXTERNAL_ACCESS 的程序集,通過一些複雜的路徑,落入 EXECUTE AS 路徑下。當“dbo”無法映射到有效登錄時,就會出現問題。dbo 的登錄名是 SID 中的owner_sid值的登錄名sys.databases。除非在 CREATE DATABASE 中使用了 AUTHORIZATION 子句,否則 owner_sid 是發出 CREATE DATABASE 語句的主體的登錄 sid。大多數情況下,這是使用者登錄並發出 CREATE DATABASE 的 Windows SID。有了這些知識,人們可以很容易地想像可能出現的問題:

  • MachineA\user複製數據庫:CREATE DATABASE 由 A 本地使用者(即或)在機器 A 上發出,DomainA\user然後數據庫被複製到機器 B(通過備份/恢復或通過文件複製)。owner_sid 由文件副本以及備份/恢復保留,這在機器 B 上 owner_sid 無效。需要 EXECUTE As 的一切都失敗了,包括從數據庫載入程序集。
  • 墓碑賬戶。CREATE DATABASE 由已離開公司的使用者發布。AD 帳戶被刪除,突然 EXECUTE AS 神秘地失敗,包括載入程序集。
  • 斷開連接的筆記型電腦。當筆記型電腦連接到工作網路時,CREATE DATABASE 出現問題。在家裡,您可以使用 Windows 記憶體憑據登錄,但 EXECUTE AS 想要連接到不可用的 AD 並失敗。載入程序集也失敗。第二天上班時,問題就神秘地解決了,這時你又回到了 AD 的範圍內。
  • 參差不齊的 AD 連接。EXECUTE AS 不使用系統記憶體的憑據,每次都連接到 AD。如果 AD 連接存在問題(超時、錯誤),則這些問題表現為 EXECUTE AS 中的類似超時和錯誤,包括載入程序集

所有這些問題都可以通過簡單地執行來診斷:EXECUTE AS USER = 'dbo';在問題 db.context 中。如果它失敗並出現錯誤,那麼您的程序集載入問題的原因是dbo.

解決方案很簡單,只需強制owner_sid登錄即可。sa通常是最好的候選人:

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

有趣的是,數據庫可能看起來非常健康。表可用,您可以執行選擇、更新、刪除、創建和刪除表等。只有某些組件需要EXECUTE AS

  • 程式碼簽名要求程式碼具有 EXECUTE AS 子句
  • 裝配驗證
  • EXECUTE AS在 T-SQL 程式碼中顯式
  • Service Broker 消息傳遞(包括查詢通知)

後者是最常見的罪魁禍首,因為依賴於SqlDependency所有的應用程序似乎突然停止工作,或者出現隨機問題。本文解釋了SqlDependency最終如何依賴於 EXECUTE AS: The Mysterious Notification

引用自:https://stackoverflow.com/questions/7034969