.net - SQL Server deja de cargar el ensamblaje
sql-server logging (10)
Hemos desarrollado un ensamblaje para SQL Server 2008 R2.
La asamblea ha estado trabajando por una semana. El proceso almacenado administrado dentro del ensamblado funcionó bien durante toda la semana y luego dejó de funcionar. Hemos estado viendo este problema un par de veces. La forma de hacerlo funcionar nuevamente es reiniciar 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)
He encontrado diferentes artículos en la web.
Esta KB sugirió que podría haber restaurado la base de datos de otro servidor SQL, que juro que no.
Este blog dijo que podría toparme con esto si instalé .NET 3.5 en SQL Server 2005 pero el mío fue SQL Server 2008 R2 y no instalé nada cuando ocurre este problema.
El punto principal es que puede seguir por un período de tiempo. Simplemente deja de funcionar al azar. Entonces, si reiniciamos SQL Server, comenzará a funcionar nuevamente. He pensado que mi servidor se estaba quedando sin memoria, pero ahora, simplemente vuelvo a ver el problema. SQL Server está utilizando solo 300 MB de RAM y mi servidor tiene 16 GB de RAM. Esto parece imposible porque es que me estoy quedando sin memoria.
Ahora, quiero recopilar más información sobre este problema. ¿Algún registro que pueda activar y mirar? Cualquier sugerencia que ayude a solucionar este problema es bienvenido.
He ejecutado algunas consultas 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>
* ACTUALIZACIÓN *
En mi SQL Server, he creado cuatro bases de datos. Cada uno de ellos con la misma asamblea unida a él. Ahora, SQL Server se negó a cargar el ensamblado y me dio el error anterior.
SELECT * from sys.dm_clr_appdomains
me muestra que en ese momento solo había un dominio de aplicación cargado y SELECT * from sys.dm_clr_loaded_assemblies
me mostró que no había ningún ensamblado cargado.
Luego, ejecuté el mismo proceso almacenado en las otras tres bases de datos. Funcionó y cargó con éxito los ensamblados y ejecutó con éxito el proceso almacenado. Después de ejecutar el proceso almacenado SELECT * from sys.dm_clr_appdomains
ahora me muestra que solo hay cuatro appdomain cargado y SELECT * from sys.dm_clr_loaded_assemblies
me mostró que ahora hay tres ensamblados cargados.
Esto tiene sentido. Ahora, espero que si ejecuto el proceso almacenado de nuevo en la base de datos original, debería cargar el ensamblaje como estaba. Adivina qué. No, no es así. Todavía me da el mismo error. Parece que esta base de datos está completamente atascada. La única forma de solucionarlo es reiniciar el servidor SQL. Estoy esperando que haya una bandera / cerradura en algún lugar de la mesa del sistema sosteniendo esto. No puedo encontrarlo. Cualquier idea es bienvenida.
Ahora, mi SQL Server está en el estado que me exige reiniciar para que funcione nuevamente.
* ACTUALIZACIÓN (31/08/2011) *
Parece que está relacionado con el propietario de la base de datos de la base de datos. Esto es un poco complicado Tenemos dos sitios y dos bosques AD. La máquina de SQL Server está unida al bosque A, pero el propietario de la base de datos es del bosque B. La conexión entre el bosque A y el bosque B no es tan estable, ya que están en dos sitios diferentes físicamente conectados por WAN.
Una vez que cambio el propietario de la base de datos a un inicio de sesión de SQL (cuenta que no es de Windows), mi proceso almacenado se ha estado ejecutando durante un par de semanas hasta ahora sin interrupción.
Aceptaré la respuesta si alguien puede explicarlo.
¡El problema en mi caso fue que la restauración de DB se ejecutó con la Autenticación de Windows en SQL Server! Droping DB, iniciando con sa, restaurando DB nuevamente y estableciendo TRUSTWORTHY ON, ¡resolvió mi problema!
¿A qué espacios de nombres hace referencia en el ensamblado? SQL Server solo admite oficialmente un handful de las referencias que .net tiene disponibles.
He visto exactamente el mismo problema al hacer referencia a System.DirectoryServices (no compatible). Teníamos una función valorada en la tabla clr que funcionaría bien durante una semana más o menos y luego, de repente, sería un error. Una redistribución o el reciclaje del servicio solucionaría temporalmente el problema.
Asegúrese de que todas las referencias de su espacio de nombres sean compatibles. De lo contrario, puede potencialmente derribar la base de datos.
En caso de que alguien se encuentre con este problema, la solución que funcionó para mí fue:
ALTER AUTHORIZATION ON DATABASE::[mydb] TO sa;
seguido por
ALTER DATABASE [mydb] SET TRUSTWORTHY ON;
Estoy restaurando mi base de datos con la cuenta de administrador, y nada más que la combinación de estas dos llamadas me ha funcionado.
Sustituye [mydb] por [yourdatabasenameame]
Esto es extraño. Tuve el mismo problema pero confirmé que la cuenta de dbo era válida mediante la ejecución de una consulta rápida: SELECCIONE ''PRUEBA'' COMO Prueba EJECUTAR COMO USUARIO = ''dbo'' También verifiqué que Trustworthy se estableció en True.
Lo que lo solucionó para mi caja fue cambiar el "propietario del ensamblado" de dbo a mi propio usuario y luego volver a dbo.
Lo experimenté. parece cuando restaura una base de datos TRUSTWORTHY configurada en OFF. entonces mi solución fue encenderlo:
ALTER DATABASE [myDB] SET TRUSTWORTHY ON
GO
y después de encenderlo, mis disparadores y procedimientos almacenados comenzaron a funcionar como antes.
Los ensamblados con EXTERNAL_ACCESS se encuentran, a través de una ruta intrincada, dentro de la ruta EXECUTE AS. El problema aparece cuando el ''dbo'' no se puede asignar a un inicio de sesión válido. El inicio de sesión de dbo es el inicio de sesión con el SID el valor owner_sid
en sys.databases
. A menos que se haya utilizado una cláusula AUTHORIZATION en CREATE DATABASE, owner_sid es el nombre de usuario del nombre de usuario del principal que emite la instrucción CREATE DATABASE. La mayoría de las veces este es el SID de Windows del usuario que inició sesión y emite CREATE DATABASE. Con este conocimiento en la mano uno puede imaginar fácilmente los problemas que pueden surgir:
- copiar base de datos: CREATE DATABASE fue emitida en la máquina A por un usuario local a A (es decir,
MachineA/user
oDomainA/user
) luego la base de datos se copió en la máquina B (mediante copia de seguridad / restauración o mediante copia de archivo). Owner_sid se conserva mediante la copia de archivo así como mediante la copia de seguridad / restauración, esta en la máquina B, el owner_sid no es válido. Todo lo que requiere EXECUTE As falla, incluida la carga de ensamblajes desde la base de datos. - cuenta aterrada. CREATE DATABASE fue emitido por un usuario que se fue de la empresa. La cuenta de AD se elimina y, de repente, EXECUTE AS falla misteriosamente, incluida la carga de ensamblajes.
- computadora portátil desconectada. CREAR BASE DE DATOS era un problema cuando la computadora portátil estaba conectada a la red de trabajo. En casa, puede iniciar sesión usando las credenciales de Windows, pero EXECUTE COMO quiere conectarse con el AD no disponible y falla. Cargando ensambles también falla. Los problemas se resuelven misteriosamente al día siguiente en el trabajo, cuando estás otra vez al alcance de AD.
- conectividad irregular de AD El EXECUTE AS no usa las credenciales almacenadas en caché del sistema y se conecta al AD cada vez. Si la conectividad de AD tiene problemas (tiempo de espera, errores) esos problemas se manifiestan como tiempos de espera y errores similares en EXECUTE AS, incluida la carga de ensamblajes
Todos estos problemas pueden diagnosticarse simplemente ejecutando: EXECUTE AS USER = ''dbo'';
en el contexto del problema db. Si falla con un error, la causa de los problemas de carga de su ensamblaje es el contexto EXECUTE AS de dbo
.
La solución es trivial, simplemente fuerce owner_sid
a un inicio de sesión válido. sa
es generalmente el mejor candidato:
ALTER AUTHORIZATION ON DATABASE::[<dbanme>] TO sa;
Lo curioso es que la base de datos puede parecer perfectamente saludable; las tablas están disponibles y puede ejecutar selecciones, actualizaciones, eliminaciones, crear y eliminar tablas, etc. Solo ciertos componentes requieren EXECUTE AS
:
- la firma de código requiere que el código tenga una cláusula EXECUTE COMO
- validación de ensamblaje
- explícito
EXECUTE AS
en el código T-SQL - Entrega de mensajes de Service Broker (incluidas las notificaciones de consulta)
Este último es el culpable más visto, ya que las aplicaciones que dependen de SqlDependency
parecen dejar de funcionar repentinamente o tienen problemas aleatorios. Este artículo explica cómo SqlDependency
finalmente depende de EXECUTE AS: The Mysterious Notification
Se requería una combinación de cosas en mi caso en que había copiado una base de datos de un servidor diferente y el usuario que creó la base de datos no estaba presente en el nuevo servidor.
myDB es la base de datos a la que intento acceder. validDbUser es el nombre de usuario en el nuevo servidor de base de datos al que deseo cambiar el barco propietario de la base de datos trasplantada.
USE myDB
GO
ALTER DATABASE [myDB] SET TRUSTWORTHY ON
GO
EXEC sp_changedbowner [validDbUser]
Sospecho que no está eliminando sus instancias SqlConnection
y SqlCommand
dentro de su ensamblado, razón por la cual se está quedando sin recursos. O eso o tiene una pérdida de memoria, ¿puedes publicar el código?
Tengo el mismo error y me di cuenta de lo que está mal: ¡eche un vistazo a su ID de conjunto! Es 65536 - el mío es 65538
Parece que el ID del ensamblado está codificado en un entero de 16 bits. Por lo tanto, "el servidor se está quedando sin recursos" tiene un sentido lógico.
Error de Microsoft, en mi opinión. Si ha encontrado una manera mejor que reiniciar o reiniciar el servicio, ¡por favor hágamelo saber! :)
Vimos este error al intentar actualizar columnas espaciales en un nuevo servidor que ejecutaba SQL Server 2017.
Crédito al jefe de TI en nuestra empresa cliente que descubrió que:
Sql 2017 introdujo nuevas reglas de confianza para CLR (SQL 2012 no fue un problema) ... Incluso CLR ''seguro'' debe haber sido firmado (que este dll no es) o usted tiene que forzar la confianza de la siguiente manera:
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;
Esto solucionó el problema para nosotros.