2009-03-19 7 views
7

¿Cómo se gestionan los objetos CLR (.NET) en SQL Server?¿Qué es el ciclo de vida de integración CLR de SQL Server?

El punto de entrada a cualquier código CLR de SQL Server es un método estático. Normalmente, solo creará objetos que existan dentro del alcance de ese método. Sin embargo, es posible que almacene referencias a objetos en miembros estáticos, permitiéndoles escapar del alcance de la llamada al método. Si SQL Server conserva estos objetos en la memoria a través de múltiples llamadas a procedimientos/funciones almacenadas, entonces podrían ser útiles para aplicaciones de almacenamiento en caché, aunque también serían más peligrosas.

¿Cómo trata esto SQL Server? ¿Incluso permite miembros estáticos (sin método)? Si es así, ¿cuánto tiempo los retiene en la memoria? ¿Recoge basura todo después de cada llamada CLR? ¿Cómo maneja la concurrencia?

Respuesta

6

En "Ensambles Pro SQL Server 2005" por Robin Dewson y Julian Skinner, dice que "Los ensamblados cargados en una base de datos, como otros objetos de base de datos, son propiedad de un usuario de base de datos. Todos los ensamblados pertenecen al mismo usuario en el la misma base de datos se ejecutará dentro del mismo Dominio de Aplicación. Las Asambleas propiedad de un usuario diferente se ejecutarán dentro de un Dominio de Aplicación por separado ".

Lo que esto me dice es que si trabaja con una única base de datos y todos los ensamblajes que carga con la instrucción CREATE ASSEMBLY tienen el mismo propietario, entonces sus ensamblajes se ejecutarán en el mismo dominio de aplicación. Sin embargo, estar en el mismo dominio de aplicación no significa usar la misma base de código, por lo que incluso el mismo dll se puede cargar en los mismos dominios de aplicación varias veces, y sus tipos no coincidirán, aunque tengan el mismo nombre. Cuando los tipos del mismo nombre provienen de diferentes bases de código, sus variables estáticas también serán instancias diferentes.

La única forma en que puedo ver el uso de variables estáticas de forma segura en el entorno CLR de SQL Server con varios ensamblajes es utilizar un solo ensamblaje. Puede usar la utilidad ILMerge con la opción "UnionMerge" para empaquetar todos sus ensamblajes en uno y combinar clases con el mismo nombre. Esto debería garantizar que para una base de datos determinada, en su único ensamblado, sus variables estáticas funcionen exactamente como lo harían en una aplicación independiente. Creo que es seguro asumir que el dominio de la aplicación no se descarga y recarga en cada solicitud, pero no se puede depender de que nunca se descargue, ya que eso ocurrirá siempre que haya un error no controlado (al menos si se está ejecutando en modo inseguro))

0

Desde el C# Especificación 3,0 (5.1.1)

una variable estática viene a la existencia antes de la ejecución de la constructor estático (§10.12) para su que contiene el tipo, y deja de existir cuando el dominio de aplicación asociado deja de existir.

Seguramente no va a cerrar todo el dominio de la aplicación después de cada llamada, ya que sería un poco ineficiente. Entonces sí, estos objetos estáticos permanecen allí siempre que la base de datos no se detenga o reinicie.

+0

Espero que no, pero me gustaría ver un "sí" o un "no" definitivo específicamente para SQL Server (que es definitivamente más restringido que un runtime .NET típico) –

+0

@CraigWalker and Tamas: Con respecto a la declaración sobre " sí, estos objetos estáticos permanecen allí siempre que la base de datos no se detenga o reinicie ", eso no es cierto.AppDomains se puede descargar por una variedad de razones, incluyendo: ** 1) ** automáticamente debido a la presión de la memoria, ** 2) ** cuando la configuración de seguridad del ensamblaje o la base de datos cambia, ** 3) ** si alguien EXECs ' DBCC DROPSYSTEMBUFFERS ('ALL') 'y ** 4) ** tal vez 1 o 2 formas más. –

3

SQL Server permite miembros de solo lectura estáticos si el ensamblado se implementa con un nivel de permiso Inseguro.

Prácticamente los objetos se retienen en la memoria hasta que se detiene/reinicia el servicio SQL.

En cuanto a la simultaneidad, su objeto y métodos deberían ser seguros para subprocesos como en cualquier otro lado.

Por ejemplo:

public static class MyCLRClass 
{ 
    private static readonly ReaderWriterLock rwlock = new ReaderWriterLock(); 
    private static readonly ArrayList list = new ArrayList(); 

    private static void AddToList(object obj) 
    { 
     rwlock.AcquireWriterLock(1000); 
     try 
     { 
      list.Add(obj); 
     } 
     finally 
     { 
      rwlock.ReleaseLock(); 
     } 
    } 

    [SqlProcedure(Name="MyCLRProc")] 
    public static void MyCLRProc() 
    { 
     rwlock.AcquireReaderLock(1000); 
     try 
     { 
      SqlContext.Pipe.Send(string.Format("items in list: {0}", list.Count)); 
     } 
     finally 
     { 
      rwlock.ReleaseLock(); 
     } 
    } 
} 

que utilizan tales cosas en SQL CLR y funciona.

3

No concebible; puedes crear miembros estáticos. PERO, deben marcarse como readonly para ensamblajes que tengan un PERMISSION_SET de SAFE o EXTERNAL_ACCESS. Solo un ensamblaje marcado como UNSAFE puede tener miembros estáticos grabables. Y esta restricción se debe a la naturaleza misma de los miembros estáticos: son compartidos entre subprocesos y sesiones.

Un conjunto se carga la primera vez que se accede a un método dentro de él. Se comparte para todas las sesiones, por lo que solo se puede acceder a los métodos estáticos. La idea es escribir funciones, no una aplicación, por lo que no hay mucho uso para mantener el estado. Y puede conducir fácilmente (aunque no siempre) a un comportamiento impredecible si varias sesiones se sobreescriben entre sí. Por lo tanto, no se maneja la concurrencia en absoluto, a menos que usted mismo escriba esa parte.

Se espera que una vez cargada, la clase (y el dominio de aplicación en el que reside) permanezca en la memoria hasta que se reinicie el servicio SQL Server o se cambie el valor PERMISSION_SET. Pero esto no está garantizado. De acuerdo a esta página, Memory Usage in SQL CLR:

cuando hay presión de memoria en el servidor, SQL CLR va a tratar de liberar la memoria mediante la recolección de basura se ejecuta de forma explícita y, si es necesario, descargando dominios de aplicación.

Así que son correctas en ambos casos con respecto a los miembros estáticos:

  • que pueden ser utilizados para el almacenamiento en caché (muy fresco)
  • que pueden ser más peligrosos:
    • que puede causar inesperado comportamiento
    • pueden acumular memoria ya que no existe un mecanismo inherente o evento natural para limpiarlos porque la clase se mantiene activa.

Y, la cantidad de memoria disponible para las rutinas CLR varía mucho dependiendo de si SQL Server es de 32 o 64 bits, y si está utilizando SQL Server 2005/2008/2008 R2 o el uso de SQL Server 2012/2014. Para obtener más información sobre la cantidad de memoria que SQLCLR tiene para jugar, consulte SQL Server 2012 Memory y Memory Usage in SQL CLR (igual que el primer enlace, publicado arriba de la cita).

Cuestiones relacionadas