SQL Server stops loading assembly

梦想的初衷 提交于 2019-11-28 17:11:49
Remus Rusanu

Assemblies with EXTERNAL_ACCESS are, through some convoluted path, falling under the EXECUTE AS path. The problem appears when the 'dbo' cannot be mapped to a valid login. dbo's login is the login with the SID the owner_sid value in sys.databases. Unless an AUTHORIZATION clause was used in CREATE DATABASE the owner_sid is the login sid of the principal issuing the CREATE DATABASE statement. Most times this is the Windows SID of the user logged in and issuing the CREATE DATABASE. With this knowledge in hand one can easily envision the problems that may arise:

  • copy database: CREATE DATABASE was issued on machine A by an user local to A (ie. MachineA\user or DomainA\user) then the database was copied to machine B (via backup/restore or via file copy). The owner_sid is preserved by file copy as well as by backup/restore, this on machine B the owner_sid is invalid. Everything requiring EXECUTE As fails, including loading assemblies from the database.
  • tombstoned account. CREATE DATABASE was issued by an user that has left the company. The AD account is deleted and all of the sudden EXECUTE AS mysteriously fails, including loading assemblies.
  • disconnected laptop. CREATE DATABASE was issues when the laptop was connected in the work network. At home you can log in using Windows cached credentials, but EXECUTE AS wants to connect to the unavailable AD and fails. Loading assemblies also fails. Problems mysteriously resolves itself next day at work, when you're again within reach of AD.
  • spotty AD connectivity. The EXECUTE AS does not uses system cached credentials and connects to the AD every time. If the AD connectivity has issues (timeout, errors) those issues manifest as similar timeouts and errors in EXECUTE AS, including loading assemblies

All these issues can be diagnosed by simply running: EXECUTE AS USER = 'dbo'; in the context of the problem db. It it fails with an error then the cause of your assembly load problems is the EXECUTE AS context of dbo.

The solution is trivial, simply force the owner_sid to a valid login. sa is the usually the best candidate:

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

The funny thing is that the database may seem to be perfectly healthy; tables are available and you can run selects, updates, deletes, create and drop tables etc. Only certain components require EXECUTE AS:

  • code signing requires the code to have an EXECUTE AS clause
  • assembly validation
  • explicit EXECUTE AS in T-SQL code
  • Service Broker message delivery (including Query Notifications)

The latter is the most often seen culprit, as applications relying on SqlDependency all of a sudden seem to stop working, or have random problems. This article explains how SqlDependency ultimately depends on EXECUTE AS: The Mysterious Notification

I experienced it. it seems when you restore a database TRUSTWORTHY set to OFF. so my solution was to turn it on :

ALTER DATABASE [myDB] SET TRUSTWORTHY ON
GO

and after i turned it on, my triggers and stored procedures started to work like before.

mahonya

Just in case someone comes across this problem, the solution that worked for me was:

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

followed by

ALTER DATABASE [mydb]  SET TRUSTWORTHY ON;

I am restoring my db with the Administrator account, and nothing else other than the combination of these two calls has worked for me.

Substitute [mydb] for [yourdatabasename]

A combination of things were required in my case where I had copied a database from a different server and the user who created the database was not present on the new server.

myDB is the database that I am trying to access validDbUser is the user name on the new database server that I wish to change the owner ship of the transplanted database to.

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

I have the same error and noticed what is wrong : Have a look at your assembly ID ! It is 65536 - mine is 65538

It seems the assembly ID is coded on a 16bits integer. So, "server may be running out of resources" takes a logical sense.

Microsoft bug, in my opinion. If you have find a better way than reboot or restart the service, please let me know! :)

We saw this error when trying to update spatial columns on a new server which was running SQL Server 2017.

Credit to the head of IT at our client company who found out that:

Sql 2017 introduced new trust rules for CLR (SQL 2012 wasn't a problem)... Even 'safe' CLR has to have been signed (which this dll isn't) or you have to force the trust as below:

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;

This fixed the issue for us.

Problem in my case was that DB restore was executed with Windows Authentication on SQL Server! Droping DB, loging in with sa, restoring DB again and setting TRUSTWORTHY ON, solved my problem!

What namespaces are you referencing in the assembly? SQL Server only officially supports a handful of the references that .net has available.

I've seen the exact same issue when referencing System.DirectoryServices (unsupported). We had a clr table valued function that would work great for a week or so and then, all of the sudden, would error. A redeploy or recycle of the service would temporarily fix the issue.

Make sure all of your namespace references are supported. Otherwise, you can potentially bring down the database.

This is weird. I had the same issue but I confirmed that the dbo account was valid via running a quick query: SELECT 'TEST' AS Test EXECUTE AS USER = 'dbo' I also verified that Trustworthy was set to True.

What fixed it for my box was changing the "assembly owner" from dbo to my own user and afterwards back to dbo.

I suspect you are not disposing your SqlConnection and SqlCommand instances inside your assembly, which is why it's running out of resources. Either that or it has a memory leak, can you post the code?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!