簡體   English   中英

Sql Server會話上下文限制

[英]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 ,讓引擎清除它們。 在上面的腳本中,如果將unsetfalse ,則會發現沒有會話上下文泄露。
  • 使用非NULL sentinel值來標記“已刪除”值,如空字符串。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM