[英]Sql Server Session Context Limit
我们在设置和清除会话上下文值时遇到问题。
我们收到以下错误: The value was not set for key X because the total size of keys and values in the session context would exceed the 1 MB limit
我们使用asp.net core和dapper进行数据访问。
打开连接时,我们执行sp_set_session_context
并发送4个密钥。 3是整数,1是字符串。
在测试中,字符串为null,整数小于10。
执行sql命令后,我们将会话上下文值设置为null,关闭并处置连接。
我们使用以下查询来查看内存使用情况: SELECT SUM([pages_kb]) FROM [sys].[dm_os_memory_cache_counters] WHERE [type] = 'CACHESTORE_SESSION_CONTEXT'
该查询尚未超过1MB。
有谁知道为什么我们收到这个错误?
这是一个已知的错误,已在SQL Server 2016和2017中修复 。 以下脚本将可靠地重现它:
bool unset = true;
using (var command = new SqlCommand()) {
command.CommandText = "sp_set_session_context";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@key", SqlDbType.NVarChar, 128);
command.Parameters.Add("@value", SqlDbType.Variant, -1);
for (int cycles = 0; cycles != 10; ++cycles) {
++cycles;
using (var connection =
new SqlConnection(@"Data Source=(localdb)\MSSqlLocalDB;Integrated Security=SSPI")
) {
connection.Open();
// Set as many values as we can
int keys = 0;
while (true) {
command.Connection = connection;
command.Parameters["@key"].Value = keys.ToString();
command.Parameters["@value"].Value = new String(' ', 8000);
try {
command.ExecuteNonQuery();
++keys;
} catch (SqlException e) {
Console.WriteLine("Failed setting at {0}: {1}", keys, e.Message);
break;
}
}
if (unset) {
// Now unset them
for (; keys >= 0; --keys) {
command.Connection = connection;
command.Parameters["@key"].Value = keys.ToString();
command.Parameters["@value"].Value = DBNull.Value;
try {
command.ExecuteNonQuery();
} catch (SqlException e) {
Console.WriteLine("Failed unsetting at {0}: {1}", keys, e.Message);
break;
}
}
}
}
}
}
输出:
125处的失败设置:未为键“125”设置该值,因为会话上下文中的键和值的总大小将超过1 MB的限制。
设置为120时失败:未为键“120”设置该值,因为会话上下文中的键和值的总大小将超过1 MB限制。
失败设置为115:未为键“115”设置该值,因为会话上下文中的键和值的总大小将超过1 MB限制。
设置失败为110:未为密钥“110”设置该值,因为会话上下文中密钥和值的总大小将超过1 MB限制。
105处的设置失败:没有为密钥“105”设置该值,因为会话上下文中的密钥和值的总大小将超过1 MB的限制。
每个周期可用的上下文大小都会减小。 如果持续时间足够长,它将降至某个最小值(不一定为0)。 此时,查询sys.dm_os_memory_cache_counters
表明使用的远不到1 MB,但即便如此,也不能再设置会话上下文。
SQL Server 2016 SP1 CU8和SQL Server 2017 CU6中已修复此错误。 (如果对key参数使用NULL
值,修复会提到清除内存问题,但是首先不允许对键使用NULL
值,即使在旧版本中也会产生错误。根据我的测试它已被修复为未设定的值 。)
对于以前的版本,至少有两种解决方法:
NULL
,让引擎清除它们。 在上面的脚本中,如果将unset
为false
,则会发现没有会话上下文泄露。 NULL
sentinel值来标记“已删除”值,如空字符串。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.