R. *_* S. 8 .net c# sql-server sqlclr
我在安全级别=的C#6.0 .NET 3.5 CLR程序集中编写了一些代码external_access.
减少代码:
public static readonly DataTable warnings_table = init_warnings_table();
public static void set_warning(string msg)
{
var row = warnings_table.NewRow();
row[1] = DateTime.Now;
row[2] = msg;
...
warnings_table.Rows.Add(row);
}
[Microsoft.SqlServer.Server.SqlProcedure]
public static SqlInt32 wrapper_func(SqlInt32 param)
{
return big_func(Param.Value);
}
int big_func(int param)
{
SqlBulkCopy bulkcopy;
....
set_warning("Message");
....
write_warnings(bulkcopy);
warnings_table.Clear();
}
Run Code Online (Sandbox Code Playgroud)
warnings_table如果wrapper_func将同时从2个或更多个不同的连接/会话中调用,将会发生什么?静态字段有写操作warnings_table.所以,我想,但不确定,这将导致数据竞争条件.
换一种说法:
static read-onlySQLCLR中的变量是否对每个sql连接/ sql查询/事务都是唯一的,或者它们是否在不同的SQLCLR过程调用之间共享数据?
是否有可能拥有无痛的全局状态,不受其他SQLCLR程序调用的影响?
static read-onlySQLCLR中的变量是否对每个sql连接/ sql查询/事务都是唯一的,或者它们是否在不同的SQLCLR过程调用之间共享数据?
驻留在SQL Server内部的程序集(即SQLCLR)将加载到单个App域中,该App域在所有会话中共享.可以存在多个应用程序域,因为它们特定于每个数据库和所有者(即授权)组合.但是任何一个特定的SQLCLR对象只会驻留在一个特定的程序集中,因此对它的所有调用都会共享该单个实例.这就是所有SQLCLR方法都需要的原因static,因为它们不是每个会话.所以,是的,静态成员/类变量是共享的,这就是为什么他们需要被声明为readonly,否则大会需要有一个PERMISSION_SET的UNSAFE,如果一个静态类变量没有标记为readonly.
是否有可能拥有无痛的全局状态,不受其他SQLCLR程序调用的影响?
不,至少不是以任何简单的内置方式.作为Collection的静态类变量可以被认为是在tempdb(与全局临时表 - 不同##Table)中创建的真实表.一旦创建了变量,它就会保留,并且一旦创建它的"会话"结束就不会消失,但所有会话都可以访问它.因此,如果您需要按会话分离,那么您需要将静态集合的属性作为区分因素 - 告诉每个会话.并且您可以获得当前的session_id/@@ SPID并使用它,只要您清除在每个进程开始时具有相同session_id的所有条目,因为SQL Server会重用session_id值.但是没有办法清除未重复使用的session_id值的条目,除非您在流程结束时执行最后一步(如果流程遇到异常,则可能不会调用该步骤).所以,并非不可能,但需要一点工作和大量的测试:-).
还应该理解,这不是特定于SQLCLR存储过程,而是影响在特定App域中运行的所有方法和对象.意思是,静态类变量与可以访问类的所有代码共享,可以是SQLCLR触发器,函数,也可能是用户定义的聚合和用户定义的类型.
请注意,关于静态变量以及SQL Server如何管理内存,您需要了解的一个细微差别是:
有时,SQL Server(如果物理内存不足)可能会决定卸载一个或多个App域.您可以通过搜索"内存压力"在SQL Server错误日志中看到此行为,因为将有以下形式的条目:
AppDomain X({database_name}.{owner_name} [runtime] .Y)由于内存压力而被标记为卸载.
卸载App Domain将清除静态变量.当在下次调用SQLCLR对象时重新加载它时,将再次创建静态变量.
因此,如果静态变量用于维持"正确"操作所需的调用之间的状态,那么您需要找到另一种方式,因为无法保证在调用之间存在数据.
如果您需要每会话全局状态,则需要使用SQL Server内置机制,方法Context Connection = true;是使用连接字符串作为T-SQL语句.您可以使用:
有关一般使用SQLCLR的更多信息,请参阅我在SQL Server Central上就此主题撰写的系列文章(需要免费注册):
| 归档时间: |
|
| 查看次数: |
521 次 |
| 最近记录: |