Подтвердить что ты не робот

SQL Server перестает загружать сборку

Мы разработали сборку для SQL Server 2008 R2.

Сборка работает уже неделю. Управляемая хранимая процедура внутри сборки работала нормально в течение всей недели, а затем перестала работать. Мы видели эту проблему пару раз. Способ заставить его работать снова - перезапустить 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)

Я нашел разные статьи в Интернете.

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

Этот блог сказал, что я могу столкнуться с этим, если я установил .NET 3.5 на SQL Server 2005, но мой был SQL Server 2008 R2, и я ничего не установил, когда это проблема возникает.

Главное, что он может продолжать действовать в течение определенного периода времени. Он просто перестает работать случайным образом. Затем, если мы перезапустим SQL Server, он снова начнет работать. Я думал, что у моего сервера действительно закончилась нехватка памяти, но теперь я снова вижу проблему. SQL Server использует только ОЗУ 300 МБ, а на моем сервере - 16 ГБ. Это кажется невозможным, потому что у меня заканчивается память.

Теперь я хочу получить дополнительную информацию по этой проблеме. Любой журнал, на который я могу включить и посмотреть? Любое предложение, помогающее устранить эту проблему, приветствуется.

Я выполнил некоторые 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>

* ОБНОВЛЕНИЕ *

На моем SQL Server я создал четыре базы данных. Каждый из них с одной и той же сборкой прикреплен к ней. Теперь SQL Server отказался загружать сборку и дал мне вышеуказанную ошибку.

SELECT * from sys.dm_clr_appdomains показывает, что в этот момент было загружено только одно приложение и SELECT * from sys.dm_clr_loaded_assemblies показало, что загруженных сборок не было.

Затем я запустил один и тот же сохраненный процесс в трех других базах данных. Он работал и успешно загружал сборки и успешно выполнял хранимую процедуру. После выполнения хранимой процедуры. SELECT * from sys.dm_clr_appdomains теперь показывает мне, что загружено всего четыре приложения и SELECT * from sys.dm_clr_loaded_assemblies показал, что теперь загружаются три сборки.

Это имеет смысл. Теперь я надеюсь, что если я запустил сохраненный процесс снова в исходной базе данных, он должен как можно скорее загрузить сборку. Угадай, что. Нет, нет. Это все равно дает мне ту же ошибку. Похоже, эта база данных полностью застряла. Единственный способ исправить это - перезагрузить SQL Server. Я надеюсь, что есть флаг/замок где-нибудь в системной таблице, поддерживая это. Я не могу это найти. Любая идея приветствуется.

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

* ОБНОВЛЕНИЕ (8/31/2011) *

Похоже, что это связано с владельцем базы данных базы данных. Это довольно сложно. У нас есть два участка и два леса AD. Машина SQL Server соединена с лесом A, но владелец базы данных из леса B. Связь между лесом A и лесом B не является стабильной, поскольку они находятся на двух разных сайтах, физически связанных WAN.

Как только я изменю владельца базы данных на учетную запись SQL (учетная запись, отличная от Windows), моя сохраненная процедура работает на пару недель до сих пор без прерывания.

Я приму ответ, если кто-нибудь сможет это объяснить.

4b9b3361

Ответ 1

Ассембли с EXTERNAL_ACCESS через некоторый запутанный путь попадают под путь EXECUTE AS. Проблема возникает, когда "dbo" не может быть сопоставлен с допустимым логином. dbo login - это логин с SID значением owner_sid в sys.databases. Если в CREATE DATABASE не использовалось условие AUTHORIZATION, owner_sid является логином входа в систему принципала, выдающего инструкцию CREATE DATABASE. В большинстве случаев это SID Windows для входа пользователя в систему и выдача CREATE DATABASE. С учетом этих знаний можно легко представить себе проблемы, которые могут возникнуть:

  • копировать базу данных: CREATE DATABASE была выпущена на машине A пользователем, локальным для A (т.е. MachineA\user или DomainA\user), после чего база данных была скопирована на машину B (через резервное копирование/восстановление или через копию файла). Владелец_sid сохраняется копией файла, а также резервным копированием/восстановлением, это на машине B owner_sid недействительно. Все, что требует EXECUTE Как не удается, включая загрузку сборок из базы данных.
  • надгробная учетная запись. CREATE DATABASE была выпущена пользователем, который покинул компанию. Учетная запись AD удалена, и все внезапные EXECUTE AS таинственно терпят неудачу, включая загрузку сборок.
  • отключен ноутбук. CREATE DATABASE была проблема, когда ноутбук был подключен в рабочей сети. Дома вы можете войти в систему с использованием кэшированных учетных данных Windows, но EXECUTE AS хочет подключиться к недоступному AD и не удается. Загрузка сборок также не выполняется. Проблемы загадочно решаются на следующий день на работе, когда вы снова находитесь в пределах досягаемости AD.
  • Точечная связь AD. EXECUTE AS не использует системные кешированные учетные данные и каждый раз подключается к AD. Если у AD-соединения есть проблемы (тайм-аут, ошибки), эти проблемы проявляются в виде аналогичных тайм-аутов и ошибок в EXECUTE AS, включая загрузку сборок

Все эти проблемы могут быть диагностированы простым запуском: EXECUTE AS USER = 'dbo'; в контексте проблемы db. Он не работает с ошибкой, поэтому причиной проблем с загрузкой сборки является контекст EXECUTE AS dbo.

Решение тривиально, просто принудительно введите owner_sid в действительный логин. sa обычно является лучшим кандидатом:

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

Самое смешное, что база данных может показаться совершенно здоровой; доступны таблицы, и вы можете выполнять выбор, обновление, удаление, создание и удаление таблиц и т.д. Только для некоторых компонентов требуется EXECUTE AS:

  • Подписание кода требует, чтобы код имел предложение EXECUTE AS
  • проверка сборки
  • Явный EXECUTE AS в коде T-SQL
  • Доставка сообщений сервис-брокера (включая уведомления о запросах)

Последний является наиболее часто наблюдаемым преступником, поскольку приложения, полагающиеся на SqlDependency, внезапно перестают работать или имеют случайные проблемы. В этой статье объясняется, как SqlDependency в конечном счете зависит от EXECUTE AS: Таинственное уведомление

Ответ 2

Я испытал это. кажется, что при восстановлении базы данных TRUSTWORTHY установлено значение OFF. поэтому я решил включить его:

ALTER DATABASE [myDB] SET TRUSTWORTHY ON
GO

и после того, как я включил его, мои триггеры и хранимые процедуры начали работать, как раньше.

Ответ 3

На всякий случай кто-то сталкивается с этой проблемой, решение, которое сработало для меня, было:

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

за которым следует

ALTER DATABASE [mydb]  SET TRUSTWORTHY ON;

Я восстанавливаю свой db с помощью учетной записи администратора, и ничто другое, кроме комбинации этих двух вызовов, не сработало для меня.

Замените [mydb] для [yourdatabasename]

Ответ 4

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

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

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

Ответ 5

Мы увидели эту ошибку при попытке обновить пространственные столбцы на новом сервере, на котором работал SQL Server 2017.

Благодарим руководителя отдела информационных технологий нашей компании-клиента, который узнал, что:

В Sql 2017 были введены новые правила доверия для CLR (SQL 2012 не был проблема)... Даже "безопасный" CLR должен быть подписан (что это DLL нет) или вы должны заставить доверие, как показано ниже:

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;

Это исправило проблему для нас.

Ответ 6

У меня такая же ошибка и я заметил, что не так: Посмотрите на свой идентификатор сборки! Это 65536 - мой - 65538

Кажется, что идентификатор сборки кодируется по целому числу 16 бит. Таким образом, "сервер может исчерпать ресурсы" имеет логический смысл.

Ошибка Microsoft, на мой взгляд. Если у вас есть лучший способ, чем перезагрузка или перезапуск службы, пожалуйста, дайте мне знать!:)

Ответ 7

В моем случае проблема заключалась в том, что восстановление БД выполнялось с помощью проверки подлинности Windows на SQL Server! Droping DB, вход в систему с sa, восстановление базы данных и настройка TRUSTWORTHY ON, решена моя проблема!

Ответ 8

Какие пространства имен вы указываете в сборке? SQL Server официально поддерживает несколько ссылок, которые доступны .net.

Я видел ту же самую проблему при ссылке на System.DirectoryServices(неподдерживаемый). У нас была функция оценки clr table, которая отлично работала бы неделю или около того, а затем внезапно возникла бы ошибка. Повторное развертывание или переработка службы временно устранит проблему.

Убедитесь, что все ваши ссылки на пространство имен поддерживаются. В противном случае вы можете сбивать базу данных.

Ответ 9

Это странно. У меня была одна и та же проблема, но я подтвердил, что учетная запись dbo действительна с помощью быстрого запроса: Тест SELECT 'TEST' AS EXECUTE AS USER = 'dbo' Я также подтвердил, что для Trustworthy установлено значение True.

Что зафиксировало это для моего ящика, было изменение "владельца сборки" от dbo на моего собственного пользователя, а затем обратно в dbo.

Ответ 10

Я нашел ту же проблему. В моем случае сборка CLR была скомпилирована для процессора x86. После того, как я изменил процессор на ЛЮБОЙ ЦП, эта проблема была решена, поскольку мой сервер SQL 64-разрядный.

Я надеюсь, что это полезно.

Ответ 11

Я подозреваю, что вы не располагаете экземплярами SqlConnection и SqlCommand внутри своей сборки, поэтому в нем заканчиваются ресурсы. Либо это, либо имеет утечку памяти, можете ли вы опубликовать код?