Что такое жизненный цикл интеграции CLR SQL Server? - PullRequest
7 голосов
/ 19 марта 2009

Как объекты CLR (.NET) управляются в SQL Server?

Точка входа в любой код CLR из SQL Server является статическим методом. Обычно вы создаете только те объекты, которые существуют в области действия этого метода. Тем не менее, вы можете хранить ссылки на объекты в статических членах, позволяя им избегать области вызова метода. Если SQL Server сохраняет эти объекты в памяти при нескольких вызовах хранимых процедур / функций, то они могут быть полезны для кэширования приложений, хотя они также будут более опасными.

Как SQL Server относится к этому? Это даже позволяет (не метод) статические члены? Если да, то как долго они сохраняются в памяти? Собирает ли мусор все после каждого вызова CLR? Как это обрабатывает параллелизм?

Ответы [ 5 ]

6 голосов
/ 28 октября 2009

В «Сборках Pro SQL Server 2005» Робина Дьюсона и Джулиана Скиннера говорится, что «Сборки, загруженные в базу данных, как и другие объекты базы данных, принадлежат пользователю базы данных. Все сборки принадлежат одному пользователю в одном и том же пользователе. база данных будет работать в одном домене приложений. Сборки, принадлежащие другому пользователю, будут работать в отдельном домене приложений. "

Это говорит мне о том, что если вы работаете с одной базой данных и все сборки, которые вы загружаете с помощью оператора CREATE ASSEMBLY, имеют одного владельца, то все ваши сборки будут работать в одном домене приложения. Однако нахождение в одном и том же домене приложений не означает использование одной и той же базы кода, поэтому даже одна и та же библиотека DLL может быть загружена в одни и те же домены приложений несколько раз, и ее типы не будут совпадать, даже если они имеют одно и то же имя. Когда одноименные типы принадлежат разным базам кода, их статические переменные также будут разными экземплярами.

Единственный способ безопасно использовать статические переменные в среде CLR SQL Server с несколькими сборками - это просто использовать одну сборку. Вы можете использовать утилиту ILMerge с опцией «UnionMerge», чтобы упаковать все свои сборки в один и объединить классы с одинаковыми именами. Это должно гарантировать, что для данной базы данных в вашей единственной сборке ваши статические переменные будут работать так же, как в автономном приложении. Я думаю, что можно с уверенностью предположить, что домен приложения не выгружается и не перезагружается при каждом запросе, но вы не можете зависеть от того, что он никогда не выгружается, поскольку это происходит всякий раз, когда возникает необработанная ошибка (по крайней мере, если она работает в небезопасном режиме ).

3 голосов
/ 05 декабря 2014

не постижимо; Вы очень можете создавать статические члены. НО, они должны быть помечены как readonly для сборок, которые имеют PERMISSION_SET либо SAFE, либо EXTERNAL_ACCESS. Только сборка, помеченная как UNSAFE, может иметь доступные для записи статические элементы. И это ограничение связано с самой природой статических элементов: они разделены между потоками и сеансами.

Сборка загружается при первом обращении к методу внутри нее. Он используется всеми сессиями, поэтому доступны только статические методы. Идея состоит в том, чтобы писать функции, а не приложение, поэтому в поддержании состояния не так много пользы И это может легко (хотя, конечно, не всегда) привести к непредсказуемому поведению, если различные сеансы перезаписывают друг друга. Таким образом, параллелизм вообще не обрабатывается, если вы сами не напишите эту часть.

Следует ожидать, что после загрузки класс (и домен приложения, в котором он находится) будет оставаться в памяти до тех пор, пока служба SQL Server не перезапустится или не изменится значение PERMISSION_SET. Но это не гарантировано. Согласно этой странице, Использование памяти в SQL CLR :

при наличии нехватки памяти на сервере SQL CLR попытается освободить память путем явного запуска сборки мусора и, при необходимости, выгрузки доменов приложений.

Итак, вы правы в обоих случаях относительно статических членов:

  • их можно использовать для кеширования (очень круто)
  • они могут быть опаснее:
    • они могут вызвать неожиданное поведение
    • они могут связать память, поскольку не существует встроенного механизма или естественного события для их очистки, потому что класс остается активным.

И объем памяти, доступный для подпрограмм CLR, сильно варьируется в зависимости от того, является ли SQL Server 32- или 64-разрядным, а также используете ли вы SQL Server 2005/2008/2008 R2 или SQL Server 2012/2014. на сколько памяти SQLCLR нужно играть, посмотрите Память SQL Server 2012 и Использование памяти в SQL CLR (аналогично первой ссылке, размещенной над цитатой).

3 голосов
/ 28 августа 2009

SQL Server допускает статические элементы только для чтения, если сборка развернута с небезопасным уровнем разрешений.

Практически объекты сохраняются в памяти до тех пор, пока служба SQL не будет остановлена ​​/ перезапущена.

Что касается параллелизма, ваш объект и методы должны быть поточно-ориентированными, как и везде.

Например:

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();
        }
    }
}

Я использую такие вещи в SQL CLR, и это работает.

1 голос
/ 20 марта 2009

Вот некоторая информация, которую я нашел.

Проблемы с общим состоянием и анонимными делегатами в SQLCLR

Мало того, что общее состояние не разрешено в сборке, отличной от UNSAFE, но анонимные делегаты (к сожалению) вызывают это ограничение "общего состояния".

0 голосов
/ 19 марта 2009

Из спецификации C # 3.0 (5.1.1)

Появляется статическая переменная до выполнения статического конструктор (§10.12) для его содержащий тип и перестает существовать когда связанный домен приложения перестает существовать.

Конечно, он не собирается закрывать весь домен приложения после каждого вызова, так как это будет немного неэффективно. Так что да, эти статические объекты остаются там до тех пор, пока база данных не будет остановлена ​​или перезапущена.

...