В SQL Server CLR Threadsafe

У меня есть интерфейс в CLR между SQL Server и веб-службами Exchange для синхронизации и отправки электронных писем между приложениями. При тестировании это работает без проблем; мы наблюдаем спорадические проблемы в производственной среде, когда более длительные задачи веб-службы перекрываются.

Мой вопрос очень прост, и я не могу решить, прочитав подробности CLR в MSDN - CLR Thread Safe или не из коробки.

Если нет, то лучший способ сделать вызовы CLR, которые являются потокобезопасными, - это заблокировать мои процедуры или есть менее радикальная альтернатива.


Спасибо за ваши ответы; мы подходим к тому, что это проблема EWS / олицетворения, а не проблема SQL. Мы провели новый набор нагрузочных тестов в нерабочее время в системе, и даже при большой нагрузке (в 1000 раз выше, чем приложение видело до сих пор) мы не видим проблемы с утечкой памяти / многопоточностью, поэтому мы теперь ищем в другом месте. ..


person u07ch    schedule 05.08.2010    source источник
comment
Эта ссылка не совсем тот же вопрос, но она может дать некоторую информацию: stackoverflow.com/questions/663124/   -  person dcp    schedule 05.08.2010
comment
Пожалуйста, ответьте на свой вопрос с некоторыми подробностями о вашем решении и (через два дня) примите этот ответ.   -  person    schedule 10.08.2010


Ответы (4)


Не используйте внутрипроцессную среду CLR для внешнего подключения, к веб-службам, обмену или чему-то еще. Используйте обычный процесс вне SQL Server. Вы увидите нечто большее, чем просто «спорадические» проблемы: вы исчерпаете пул рабочих процессов для событий CLR, а SQL Server зависнет.

person Remus Rusanu    schedule 05.08.2010
comment
Вы действительно видели SQL Server, заблокированный сборкой SQL CLR? SQLCLR использует общий пул потоков с механизмом БД, но означает ли это, что планировщик не может управлять потоками таким образом, чтобы избежать полного замораживания? Я нахожу это удивительным. - person Paul Keister; 07.08.2010
comment
Да я видел. Я тоже создал процедуры CLR, которые подключались к удаленным машинам (для выборки счетчиков производительности), и после трех зависаний сервера в течение двух недель мне пришлось заменить решение внешним процессом. х64 сервер. - person Remus Rusanu; 07.08.2010
comment
Ремус, самое смешное, что именно Microsoft рекомендовала этот подход к обработке электронной почты с помощью EWS/CLR. AM собирается закрыть журнал; мы подвергли систему огромной нагрузке (5000 исходящих писем каждые 30 секунд с вложениями) и не можем воспроизвести ошибку, которая заставляет нас задаться вопросом, является ли это проблемой обмена/аутентификации в EWS/DC, а не проблемой безопасности потока в SQL Сервер - person u07ch; 07.08.2010
comment
Ремус: спасибо, это хорошая информация. Могу я попросить одно уточнение: вы говорите, что весь процесс SQL Server завис или только потоки SQLCLR? - person Paul Keister; 08.08.2010
comment
Весь SQL, из рабочих. Когда вы говорите «рекомендуется Microsoft», вы имеете в виду поле MCS SQL Server, рекомендованное для использования в CLR в процессе? - person Remus Rusanu; 08.08.2010
comment
Никогда не верьте тому, что вам говорит MCS. Большинство из этих парней понятия не имеют. - person ; 11.08.2010

Ответ на самом деле зависит от того, как вы пишете свой код .Net И как вы регистрируете свою сборку. По умолчанию и по общему предпочтению сборки SQLCLR создаются как БЕЗОПАСНЫЕ, что означает, что SQL Server сканирует сборку при ее создании (фактическая инструкция CREATE ASSEMBLY), чтобы определить, соответствует ли она правилам БЕЗОПАСНОЙ сборки. Сборка SAFE не имеет переменных экземпляра, доступных только для чтения. Это означает, что все переменные являются переменными экземпляра, и если вы объявляете статическую переменную, вы должны использовать модификатор «только для чтения». Это гарантирует, что вы не будете обмениваться данными между потоками.

ОДНАКО, вы можете создать статическую переменную в классе и изменить ее, но сборка должна быть создана как НЕБЕЗОПАСНАЯ. Попытка создать его как SAFE выдаст следующую ошибку:

CREATE ASSEMBLY не удалось, так как метод «MethodName» для типа «ClassName» в безопасной сборке «AssemblyName» сохраняется в статическом поле. Сохранение в статическое поле не допускается в безопасных сборках.

Сохранение в статической переменной не является потокобезопасным, поэтому вы должны предоставить сборке разрешение UNSAFE. Но вне этого случая SQLCLR является потокобезопасным.

person Solomon Rutzky    schedule 23.01.2011
comment
Что делать, если ваша переменная static readonly установлена ​​с отражением? действительно ли это нарушает БЕЗОПАСНУЮ сборку или наличия System.Reflection достаточно, чтобы пометить сборку как UNSAFE? - person Seph; 18.04.2012
comment
@Seph, использование отражения должно быть в порядке, потому что я делаю именно это ;-). У меня есть следующий код: public static readonly int Major = Assembly.GetExecutingAssembly().GetName().Version.Major; и сборка помечена как БЕЗОПАСНАЯ без проблем с установкой или во время выполнения. - person Solomon Rutzky; 19.04.2012
comment
Я думаю, что причина, по которой статические переменные должны быть помечены как доступные только для чтения, заключается в том, что статические переменные обычно могут быть изменены более чем одним потоком одновременно. Делая их только для чтения, этого не произойдет. Однако сам объект может быть доступен/изменен несколькими потоками, и в этой ситуации вам придется использовать какую-то синхронизацию без блокировки. - person Triynko; 04.11.2013

Основная проблема, с которой вы сталкиваетесь в коде SQL CLR, — нехватка памяти, что приводит к сбросу AppDomain. Это эквивалентно сбою ОС с точки зрения вашего кода. При использовании SQLCLR вы используете отдельный пул памяти, управляемый SQL Server, который намного меньше и менее гибкий, чем вы привыкли. Мне сказали, что команда SQLCLR работает над этой проблемой.

Одно важное замечание: если вы получите сброс SQLCLR AppDomain, это не повлияет на стабильность вашего сервера в других отношениях. Сбой процедуры SQLCLR просто вернет вызывающей стороне ошибку TSQL.

person Paul Keister    schedule 07.08.2010
comment
Павел Спасибо за ваш ответ; мы провели нагрузочное тестирование веб-сервисов для отправки почтовых сообщений, отправляя 5000 одновременных сообщений снова и снова в течение нескольких часов. Мы не наблюдаем утечки памяти в приложении; и мы не видим никаких перезапусков приложений в журналах. Тот факт, что сообщения нагрузочного тестирования были доставлены без проблем, заставляет нас думать, что у нас может быть проблема с DC / EWS, поэтому мы написали несколько тысяч событий обработки ошибок и регистрации в коде, чтобы отслеживать ситуацию на данный момент. - person u07ch; 07.08.2010

Проведя много независимых тестов на CLR сейчас (преднамеренно пытаясь заставить его потерпеть неудачу), если ваш код CLR написан правильно - красиво объявите переменные со значениями инициализации, похоже, что CLR является потокобезопасным.

person u07ch    schedule 11.08.2010