wake-up-neo.net

SQL Server beendet das Laden der Assembly

Wir haben eine Assembly für SQL Server 2008 R2 entwickelt.

Die Versammlung hat eine Woche gearbeitet. Der verwaltete gespeicherte Prozess in der Assembly funktionierte für die gesamte Woche einwandfrei und funktioniert dann nicht mehr. Wir haben dieses Problem schon einige Male gesehen. Um es wieder zum Laufen zu bringen, starten Sie den SQL Server neu.

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)

Ich habe verschiedene Artikel im Web gefunden. 

Diese KB schlug vor, dass ich die Datenbank möglicherweise von einem anderen SQL Server wiederhergestellt habe, was ich schwöre, ich habe es nicht getan. 

In diesem Blog sagte ich, ich könnte auf dieses Problem stoßen, wenn ich .NET 3.5 auf SQL Server 2005 installiert habe, aber es war SQL Server 2008 R2 und ich habe nichts installiert, wenn dieses Problem auftritt.

Der Hauptpunkt ist, dass es eine Zeit lang weiterlaufen kann. Es hört einfach auf, zufällig zu arbeiten. Wenn wir dann den SQL Server neu starten, wird er wieder funktionieren. Ich habe an meinen Server gedacht, der Speicher ist knapp geworden, aber jetzt sehe ich das Problem nur noch einmal. SQL Server verwendet nur 300 MB RAM und mein Server verfügt über 16 GB RAM. Das klingt unmöglich, weil mir das Gedächtnis ausgeht.

Nun möchte ich mehr Informationen zu diesem Problem sammeln. Jedes Protokoll, das ich einschalten und ansehen kann? Vorschläge, die bei der Problembehandlung hilfreich sind, sind willkommen.

Ich habe einige SQL-Abfragen ausgeführt.

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 *

Auf meinem SQL Server habe ich vier Datenbanken erstellt. Jeder von ihnen mit der gleichen Assembly verbunden. Nun lehnte es SQL Server ab, die Assembly zu laden, und gab mir den obigen Fehler.

SELECT * from sys.dm_clr_appdomains zeigt mir an diesem Punkt, dass nur eine Domäne geladen wurde, und SELECT * from sys.dm_clr_loaded_assemblies zeigte mir, dass überhaupt keine Assemblys geladen wurden.

Dann habe ich die gleiche gespeicherte Prozedur auf den anderen drei Datenbanken ausgeführt. Es hat funktioniert, die Assemblys wurden erfolgreich geladen und die gespeicherte Prozedur wurde erfolgreich ausgeführt. Nach dem Ausführen des gespeicherten proc. SELECT * from sys.dm_clr_appdomains zeigt jetzt an, dass nur vier Domänen geladen sind, und SELECT * from sys.dm_clr_loaded_assemblies zeigte mir an, dass jetzt drei Baugruppen geladen sind.

Das macht Sinn. Nun, ich hoffe, wenn ich die gespeicherte Prozedur erneut in der ursprünglichen Datenbank starte, sollte die Assembly so geladen werden, wie sie war. Erraten Sie, was. Nein, das stimmt nicht. Es gibt mir immer noch den gleichen Fehler. Es sieht so aus, als ob diese Datenbank vollständig blockiert ist. Die einzige Möglichkeit, dies zu beheben, besteht darin, den SQL Server neu zu starten. Ich hoffe, dass irgendwo in der Systemtabelle eine Flagge/ein Schloss vorhanden ist, die dies aufhält. Ich kann es nicht finden. Jede Idee ist willkommen.

Nun ist mein SQL Server in dem Zustand, in dem ich einen Neustart durchführen muss, damit er wieder funktioniert. 

* UPDATE (31.08.2011) *

Es klingt, als ob es mit dem Datenbankbesitzer der Datenbank zusammenhängt. Das ist irgendwie kompliziert. Wir haben zwei Standorte und zwei AD-Wälder. Die SQL Server-Maschine ist mit Gesamtstruktur A verbunden, der Datenbankbesitzer stammt jedoch aus Gesamtstruktur B. Die Verbindung zwischen Gesamtstruktur A und Gesamtstruktur B ist nicht so stabil, da sie sich an zwei verschiedenen Standorten befinden, die physisch über WAN verbunden sind.

Nachdem ich den Datenbankbesitzer in einen SQL-Login (Nicht-Windows-Konto) geändert habe, läuft meine gespeicherte Prozedur für einige Wochen ohne Unterbrechung.

Ich werde die Antwort akzeptieren, wenn es jemand erklären kann.

37
Harvey Kwok

Assemblies mit EXTERNAL_ACCESS fallen durch einen gewundenen Pfad unter den Pfad EXECUTE AS. Das Problem tritt auf, wenn das 'Dbo' keinem gültigen Login zugeordnet werden kann. Das Login von dbo ist das Login mit der SID der owner_sid-Wert in sys.databases . Wenn in CREATE DATABASE keine AUTHORIZATION-Klausel verwendet wurde, ist owner_sid die Anmeldeseite des Principals, der die CREATE DATABASE-Anweisung ausgibt. Meistens ist dies die Windows-SID des angemeldeten Benutzers und die Ausgabe der CREATE DATABASE. Mit diesem Wissen in der Hand kann man sich leicht die möglichen Probleme vorstellen:

  • datenbank kopieren: CREATE DATABASE wurde auf Maschine A von einem lokalen Benutzer (dh MachineA\user oder DomainA\user) ausgegeben. Anschließend wurde die Datenbank auf Maschine B kopiert (über Sicherung/Wiederherstellung oder über Dateikopie). Die owner_sid wird sowohl durch die Dateikopie als auch durch die Sicherung/Wiederherstellung beibehalten. Auf der Maschine B ist die owner_sid ungültig. Alles was EXECUTE As erfordert, schlägt fehl, einschließlich des Ladens von Baugruppen aus der Datenbank.
  • grabsteinkonto. CREATE DATABASE wurde von einem Benutzer ausgestellt, der das Unternehmen verlassen hat. Das AD-Konto wird gelöscht, und plötzlich schlägt EXECUTE AS auf mysteriöse Weise fehl, einschließlich dem Laden von Baugruppen.
  • getrennter Laptop. Bei CREATE DATABASE gab es Probleme, wenn der Laptop im Arbeitsnetzwerk angeschlossen war. Zu Hause können Sie sich mit zwischengespeicherten Windows-Anmeldeinformationen anmelden, EXECUTE AS möchte jedoch eine Verbindung zum nicht verfügbaren AD herstellen und schlägt fehl. Das Laden von Baugruppen schlägt ebenfalls fehl. Probleme lösen sich auf mysteriöse Weise am nächsten Tag bei der Arbeit, wenn Sie wieder in Reichweite von AD sind.
  • fleckige AD-Konnektivität. Der EXECUTE AS verwendet keine vom System zwischengespeicherten Anmeldeinformationen und stellt jedes Mal eine Verbindung zum AD her. Wenn bei der AD-Verbindung Probleme (Timeout, Fehler) auftreten, manifestieren sich diese Probleme als ähnliche Timeouts und Fehler in EXECUTE AS, einschließlich Laden von Assemblys

Alle diese Probleme können durch einfaches Ausführen von EXECUTE AS USER = 'dbo'; im Kontext der Problem-Datenbank diagnostiziert werden. Wenn es mit einem Fehler fehlschlägt, ist der EXECUTE AS-Kontext von dbo die Ursache für Ihre Assembly-Ladeprobleme.

Die Lösung ist trivial, zwingen Sie einfach den owner_sid zu einem gültigen Login. sa ist normalerweise der beste Kandidat:

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

Das Lustige ist, dass die Datenbank vollkommen gesund erscheint. Tabellen stehen zur Verfügung und Sie können Auswahl, Aktualisierungen, Löschungen, Erstellen und Löschen von Tabellen usw. ausführen. Nur bestimmte Komponenten erfordern EXECUTE AS:

  • zur Codesignierung muss der Code eine EXECUTE AS-Klausel enthalten
  • Baugruppenvalidierung
  • expliziter EXECUTE AS im T-SQL-Code
  • Zustellung von Service Broker-Nachrichten (einschließlich Abfragebenachrichtigungen)

Letzteres ist der häufigste Schuldige, da Anwendungen, die sich auf SqlDependency stützen, plötzlich aufhören zu funktionieren oder zufällige Probleme haben. Dieser Artikel erklärt, wie SqlDependency letztendlich von EXECUTE AS abhängt: Die geheimnisvolle Benachrichtigung

44
Remus Rusanu

Ich habe es erlebt. Es scheint, wenn Sie eine Datenbank wiederherstellen, die TRUSTWORTHY auf OFF gesetzt ist. Meine Lösung bestand also darin, es einzuschalten:

ALTER DATABASE [myDB] SET TRUSTWORTHY ON
GO

nachdem ich es eingeschaltet hatte, funktionierten meine Trigger und gespeicherten Prozeduren wie zuvor.

27
Ehsan Mirsaeedi

Für den Fall, dass jemand auf dieses Problem stößt, war die Lösung, die für mich funktioniert hat:

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

gefolgt von

ALTER DATABASE [mydb]  SET TRUSTWORTHY ON;

Ich stelle meine Datenbank mit dem Administratorkonto wieder her, und nichts anderes als die Kombination dieser beiden Aufrufe hat für mich funktioniert. 

[Mydb] für [yourdatabasename] ersetzen

17
mahonya

Ich habe den gleichen Fehler und habe bemerkt, was falsch ist: Schauen Sie sich Ihre Baugruppen-ID an! Es ist 65536 - meine ist 65538

Es scheint, dass die Assembly-ID in einer 16-Bit-Ganzzahl codiert ist . "Dem Server gehen möglicherweise die Ressourcen aus" hat einen logischen Sinn.

Microsoft-Fehler, meiner Meinung nach .. Wenn Sie einen besseren Weg finden, als den Dienst neu zu starten oder neu zu starten, informieren Sie mich bitte! :)

5
Hugues

In meinem Fall war eine Kombination von Dingen erforderlich, bei denen ich eine Datenbank von einem anderen Server kopiert hatte und der Benutzer, der die Datenbank erstellt hatte, auf dem neuen Server nicht vorhanden war.

myDB ist die Datenbank, auf die ich zugreifen möchte validDbUser ist der Benutzername auf dem neuen Datenbankserver, in den ich das Eignerschiff der transplantierten Datenbank ändern möchte.

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

Dieser Fehler ist aufgetreten, als versucht wurde, räumliche Spalten auf einem neuen Server zu aktualisieren, auf dem SQL Server 2017 ausgeführt wurde.

Wir danken dem IT-Leiter unserer Kundenfirma, der Folgendes herausgefunden hat:

SQL 2017 führte neue Vertrauensregeln für CLR ein (SQL 2012 war kein Problem) ... Sogar "sichere" CLR muss signiert sein (was diese DLL Nicht ist), oder Sie müssen die vertrauen wie folgt:

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;

Dies hat das Problem für uns behoben.

3
Ian Grainger

Problem in meinem Fall war, dass die Wiederherstellung der Datenbank mit der Windows-Authentifizierung auf SQL Server ausgeführt wurde! DB fallenlassen, sich mit sa einloggen, DB wiederherstellen und TRUSTWORTHY auf ON setzen, mein Problem wurde gelöst!

1
100r

Welche Namespaces referenzieren Sie in der Assembly? SQL Server unterstützt nur offiziell ein handful der von .net verfügbaren Verweise. 

Ich habe genau das gleiche Problem gesehen, als ich auf System.DirectoryServices verwies (nicht unterstützt). Wir hatten eine Clr-Tabelle mit einer wertvollen Funktion, die gut für eine Woche funktionieren würde, und dann würden wir plötzlich einen Fehler machen. Eine erneute Bereitstellung oder Wiederverwendung des Dienstes würde das Problem vorübergehend beheben.

Stellen Sie sicher, dass alle Ihre Namespace-Referenzen unterstützt werden. Andernfalls können Sie möglicherweise die Datenbank herunterfahren.

0
brian

Das ist komisch. Ich hatte das gleiche Problem, bestätigte jedoch, dass das Dbo-Konto gültig war, indem eine kurze Abfrage ausgeführt wurde: SELECT 'TEST' AS Test EXECUTE AS USER = 'Dbo' Wahr.

Das Problem, das für meine Box behoben wurde, war der Wechsel des "Assembly Owner" von dbo zu meinem eigenen Benutzer und anschließend wieder zu dbo.

0
regeter