2011-08-12 52 views
34

我們爲SQL Server 2008 R2開發了一個程序集。SQL Server停止加載程序集

大會已經工作了一個星期。組件內部的託管存儲過程在整個星期內工作正常,然後停止工作。我們幾次都看到這個問題。再次運行它的方法是重新啓動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> 

* UPDATE *

在我的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帳戶),我的存儲過程已經運行了幾個星期,至今沒有中斷。

如果有人能解釋它,我會接受答案。

+0

嘗試運行perfmon並查看硬件是否無法處理負載。 – 2011-08-12 03:06:00

+0

「它隨機停止工作。」 - 更可能是您的程序集中發生錯誤(例如數據轉換錯誤) –

+0

@ Surfer513:這不太可能是原因。 –

回答

37

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

  • 複製數據庫:CREATE DATABASE通過本地的(即MachineA\userDomainA\user)的用戶機器A發出則數據庫被複制到機器B(通過備份/恢復或通過文件複製)。 owner_sid通過文件複製以及備份/恢復來保存,這在機器B上owner_sid是無效的。需要EXECUTE的所有內容均失敗,包括從數據庫加載程序集。
  • 墓碑賬戶。 CREATE DATABASE由離開公司的用戶發佈。 AD帳戶被刪除,突然EXECUTE AS神祕失敗,包括加載程序集。
  • 斷開筆記本電腦。當筆記本電腦連接到工作網絡時,CREATE DATABASE問題成爲問題。在家中,您可以使用Windows緩存的憑據登錄,但EXECUTE AS希望連接到不可用的AD並失敗。加載程序集也失敗。當你再次接觸到AD時,問題會在工作中神祕地解決。
  • 斑點AD連接。 EXECUTE AS不會使用系統緩存憑據,並且每次都連接到AD。EXECUTE AS USER = 'dbo';的問題分貝的情況下:如果AD連接有問題(超時錯誤)表現爲類似超時和EXECUTE AS錯誤,包括加載組件這些問題

所有這些問題都可以通過簡單的運行進行診斷。它失敗並出現錯誤,則導致程序集加載問題的原因是dbo的EXECUTE AS環境。

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

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

有趣的是,數據庫似乎是完全健康的;表可用,您可以運行選擇,更新,刪除,創建和刪除表等,只有某些組件需要EXECUTE AS

  • 代碼簽名要求的代碼有一個EXECUTE AS子句
  • 裝配驗證
  • 明確EXECUTE AS在T-SQL代碼
  • 服務代理消息傳遞(包括查詢通知)

後者是最經常看到的罪魁禍首,一個那麼依靠SqlDependency的應用程序突然間似乎停止工作,或者產生了隨機問題。這篇文章解釋瞭如何最終取決於EXECUTE AS:The Mysterious Notification

+0

我認爲你是給出最佳答案的人。我將在下次遇到問題時嘗試EXECUTE AS USER ='dbo'。我相信這是問題。 –

+0

EXECUTE AS USER ='dbo'; 適用於我。 但是你的建議治癒方法:ALTER AUTHORIZATION ON DATABASE :: [] TO sa; 工作就像一個魅力 - 所以非常感謝:) –

+0

@PaulHutchinson:嗯...這是有趣的,種類的廢墟我對發生了什麼事情的理解。很高興知道它對你有幫助,但我需要做一些未來的digg來了解你的情況... –

0

你在程序集中引用了哪些名稱空間? SQL Server僅正式支持.net可用的引用的handful

我在引用System.DirectoryServices(不支持)時看到了完全相同的問題。我們有一個可以工作一個星期左右的clr表值函數,然後突然出現錯誤。重新部署或回收服務將暫時解決問題。

確保您的所有名稱空間引用都受支持。否則,您可能會關閉數據庫。

+0

Nah,我沒有註冊任何不受支持的程序集到我們的SQL Server。我有一個且只有一個程序集註冊。這是我爲存儲過程創建的程序集。該程序集的安全級別設置爲「EXTERNAL_ACCESS」。 –

0

我懷疑你沒有在你的程序集中部署你的SqlConnectionSqlCommand實例,這就是爲什麼它的資源不足。無論是它還是它有內存泄漏,你可以發佈代碼?

+0

感謝您的建議和抱歉,這裏發佈代碼基本上是不可能的。我們有大約40個存儲過程,代碼並不簡單。我聽到你。有可能我們可能會有一些泄漏,從而導致資源錯誤。我們已經將我們的MemToLeave設置(用於.NET的內存SQL服務器,鏈接服務器和其他一些東西)設置爲1GB。當時它失敗了,我檢查了內存,SQL Server根本沒有使用1GB的內存。我們得出結論,它與壞鏈接有關,我們使用遠程林域用戶作爲數據庫所有者。 –

5

我有同樣的錯誤,並注意到有什麼不對: 看看你的程序集ID! 這是65536 - 我的是65538

看起來程序集標識符編碼在一個16位整數。 因此,「服務器可能耗盡資源」具有邏輯意義。

Microsoft bug,在我看來。 如果你找到一個更好的方法比重新啓動或重新啓動該服務,請讓我知道! :)

+1

聽起來像一個猜測,不像一個答案。你有沒有發現任何其他暗示來證明你的理論? – mbx

18

我經歷過它。看起來當你恢復數據庫TRUSTWORTHY設置爲OFF。所以我的解決辦法是將其打開:

ALTER DATABASE [myDB] SET TRUSTWORTHY ON 
GO 

後,我打開它,我的觸發器和存儲過程開始像以前一樣工作。

+0

這是爲我工作的! – devC

+0

謝謝你這完美地解決了我的問題。 – Manachi

+0

微軟顯然建議你不要這樣做。 https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/clr-strict-security。你應該按照我的回答爲每個程序集添加權限(儘管發現它的功勞並不屬於我!) –

1

問題在我的情況是,數據庫恢復與Windows身份驗證SQL服務器上執行!丟棄數據庫,使用sa登錄,重新恢復數據庫並設置TRUSTWORTHY ON,解決了我的問題!

11

萬一有人遇到這個問題,對我工作的解決方案是:依次按

ALTER DATABASE [mydb] SET TRUSTWORTHY ON; 

我恢復我的數據庫使用管理員帳戶

ALTER AUTHORIZATION ON DATABASE::[mydb] TO sa; 

,沒有別的除了這兩個調用的組合以外,它們都適用於我。

替代[MYDB]爲[yourdatabasename]

0

這很奇怪。我有同樣的問題,但我確認dbo帳戶通過運行快速查詢是有效的: SELECT'TEST'AS Test EXECUTE AS USER ='dbo' 我也驗證了Trustworthy設置爲True。

什麼固定它爲我的箱子正在改變「集會所有者」從dbo到我自己的用戶,然後回到dbo。

1

在我從另一臺服務器複製數據庫並且創建數據庫的用戶不在新服務器上的情況下,需要組合一些東西。

myDB是我試圖訪問的數據庫 validDbUser是我希望將移植數據庫的所有者更改爲新數據庫服務器上的用戶名。

USE myDB 
GO 
ALTER DATABASE [myDB] SET TRUSTWORTHY ON 
GO 
EXEC sp_changedbowner [validDbUser] 
0

我們試圖更新一個新的服務器上的空間列這是在我們的客戶公司運行SQL Server 2017

感謝IT的頭部誰發現了,當看到這個錯誤:

Sql 2017爲CLR引入了新的信任規則(SQL 2012不是 問題)......即使是'安全的'CLR也必須已經簽名(這個DLL不是 ),或者您必須強制信任如下:

DECLARE @clrName nvarchar(4000) = 'sqlspatialtools, version=0.0.0.0, culture=neutral, publickeytoken=null, processorarchitecture=msil' 

DECLARE @asmBin varbinary(max) = 'PUT THE BINARY STRING HERE (GET FROM SCRIPTING CREATE TO FOR THE EXISTING ASSEMBLY' 

DECLARE @hash varbinary(64); 

SELECT @hash = HASHBYTES('SHA2_512', @asmBin); 

EXEC sys.sp_add_trusted_assembly @hash = @hash, @description = @clrName; 

這解決了我們的問題。