在 MSSQL (TSQL) 中,是否可以指定驻留在连接字符串中但不影响池化的上下文变量
本文关键字:字符串 连接 影响 变量 上下文 TSQL MSSQL 是否 | 更新日期: 2023-09-27 17:55:51
为了进一步解释需求,请考虑以下场景:
在严重依赖TRIGGERS
的遗留系统中,我们需要提供某种令牌(我们称之为"SessionID")以插入到某些安全日志表中。此令牌在应用程序服务器中以 C# 创建,并将传递到所有 SQL 命令中。
可悲的是,对触发器的这种要求是不可改变
的因此,由于我有权修改连接字符串,因此我可以(并且已成功证明我可以)使用"应用程序名称"令牌来提供此信息。
string connectionString = string.Format("SERVER=sql.example.com; "
+ "DATABASE=someDB; User ID=xyz; Password=123; Application Name={0}", sID);
既然这有效,问题出在哪里?
问题很简单...以上有效,但由于我们有成千上万的用户......我们的连接池被销毁(因为连接池是基于连接字符串创建的...基本上,我需要连接池基于除Application Name
属性之外的所有内容)。
所以,你知道我怎么做吗:
- 在连接字符串中设置一个不会包含在池中的属性。
- 以其他方式为此连接设置上下文属性,该属性对性能的影响不是很大。
作为旁注...我可以立即打开连接并创建一个具有单个值的临时表:
SELECT 12345 AS SessionID INTO #context
但这似乎非常矫枉过正!
您需要执行此操作而不是依赖连接字符串,而是可以使用临时表SET CONTEXT_INFO
/CONTEXT_INFO()
将一些任意数据与当前会话/连接相关联(并且在触发器中可用)。
如果服务器可以接受从用户/时间等的某种组合中创建变量,则可以从登录触发器中自动分配CONTEXT_INFO
,在这种情况下,您根本不需要更改连接机制。
我的理解是使用连接字符串作为键创建单独的连接池,因此对连接字符串的任何上下文修改都将不可避免地影响池化
我之前注意到 SqlConnection 类上的 WorkstationId 属性 - 这可能是引入一些上下文化的技术?
SqlConnection cn = new SqlConnection("CONNECTION_STRING");
string identifier = cn.WorkstationId;
好的,所以在做了大量的测试之后,我想出了一个解决方案。
- 关闭连接池。
- 使用"工作站 ID"属性。
在进行了一些基准测试后,我能够看到连接池比不使用池快 50 倍......但。。。不使用池化仍然每个连接只需要 0.005 秒。
我愿意忍受纳秒级的性能损失,以获得我们需要的安全日志记录。
哦,作为旁白 - 如果当前正在使用所有连接,连接池具有主要的性能限制,因为第 101 个排队的人将不得不等待......所以,在某些情况下...连接池比不使用池慢 1,000 倍!
连接字符串中的所有内容都将用于池化(我认为他们将使用 GetHashCode() 来检查字符串是否已在池中)。