2

Is it correct to assume that a static variable which shares state between SQLCLR stored procedures will not be nullified between stored procedures execution, since the stored procedures are defined in the same assembly and are executed in a batch - which enables the query optimizer to recognise it ?

2
  • I don't understand your question here. Commented Jul 10, 2017 at 19:50
  • The CLR class containing the stored procedure can contain a static variable - which can cache state. Commented Jul 10, 2017 at 21:12

2 Answers 2

2

Static variables do retain their value between executions of any methods within the Assembly (this, of course, requires that the Assembly be marked as UNSAFE). However, this has nothing to do with the Query Optimizer recognizing anything since the Query Optimizer has no insight into what is inside of the Assembly. Static variables retain their values due to the App Domain persisting until: service restart, forced unload due to memory pressure, security change made to the database containing the App Domain, security change to an Assembly in the App Domain, etc. The fact that static variables share their values between SQLCLR objects (not just stored procedures) is due to SQLCLR sharing the App Domain across all sessions.

Please note that while static variables can share values between executions, that:

  • This has nothing to do with batches. The values can be shared across query batches even.

  • It is not guaranteed that any value will always persist between all executions due to SQL Server being allowed to unload the App Domain even while a SQLCLR object is currently executing. So if two SQLCLR objects — Stored Procedures, perhaps — were executed one after the other, even in the same batch, it is possible for the App Domain to be unloaded ** prior to the execution of the 2nd Stored Procedure (i.e. between queries), and hence the App Domain would be started again to process the 2nd Stored Procedure, but with no indication of any prior calls, hence no prior state in any static variables.

    Meaning, if the value in the static variable being cleared will cause a subsequent execution of a SQLCLR object to do something unexpected, then do not use static variables for that purpose. They are fine for caching, but can be unreliable for many uses. IN FACT, there is another question, here on S.O., where someone was doing exactly this – caching some values to improve performance between executions of UPDATE statements – and ran into this problem. In that linked question, the O.P. has a main SQLCLR stored procedure that stores values in a static variable and executes other SQLCLR stored procedures that read from that static variable. The main SQLCLR stored procedure runs until its sub-calls complete successfully, but during its execution, the App Domain is marked for unload. At that point, all new SQLCLR executions happen in a new App Domain, even though the App Domain with the main SQLCLR stored procedure is still running. But, the App Domain for the main SQLCLR stored procedure has a state of "DOOMED" and cannot be accessed by any new SQLCLR calls (since any new calls happen in the new App Domain).

IF you need to persist state between executions within the same Session that is NOT shared with other Sessions, you can:

Each of those needs to be created / set in a SQLCLR stored procedure using "Context Connection = true;" as the Connection String. But they should be readable in a Scalar UDF, also using "Context Connection = true;" as the Connection String.


** An App Domain being marked for unload due to memory pressure, or due to a security change to the Database or Assembly, will not kill a currently running SQLCLR process. The App Domain remains running but is unloaded immediately upon the process completing.

HOWEVER, if the App Domain is unloaded due to .NET Integration / "clr enabled" being turned off via sp_configure, then the SQLCLR process will be immediately killed.

Sign up to request clarification or add additional context in comments.

12 Comments

Well, maybe the Query Optimizer could recognize that the same assembly is needed again and again and therefore not execute forced unloads under memory pressures ?
Nope. SQL Server will unload an App Domain whenever it feels it needs to. This has nothing to do with any future calls, even in the same batch. I updated my answer with some clarifications while you were entering your comment, so please review the updates to my answer.
Even during execution?
As far as I know, NO, the App Domain will persist during execution, even if marked for unload during execution. I do know that you can drop an Assembly during execution since the image is copied into memory.
That brings up an interesting question, though. I will have to try running a long-running SQLCLR object and during its execution, disable .NET integration / "clr enabled" and see what happens.
|
0

Writing to static variables is not supported in SQL CLR. Your AppDomains can be torn down and reloaded at any time, and so you can't rely on static variable state to be preserved between calls.

The correct place to store data is in a table, or in SESSION_CONTEXT

2 Comments

Then how can one safely use SQL CLR at all ?
@Lorin_F: By not relying on static state? The AppDomain isn't going to be torn down in the middle of a query, if that's what you're thinking -- at least not without aborting the query to maintain consistency, which is all the safety SQL Server guarantees. That you get no hard guarantees doesn't mean the feature is unusable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.