Sql-Server

在 DB 表中使用 SPID(而不是表變數)

  • July 18, 2019

用於預訂事物的事務數據庫…

我們的供應商被要求用@tablevariables 替換#temptables(因為編譯鎖很重),但他們替換為一個實際的表,該表將SPID 作為列添加,以確保儲存過程只作用於適用的行。

您認為這種操作方法有什麼風險嗎?在所有事務都被隔離在它們自己的事務中之前……我擔心我們最終可能會鎖定這個表,但他們認為 SQL 使用行級鎖定,這不會創建更多的鎖。

SQL Server 版本:2016 企業版 - 13.0.5216.0


CREATE TABLE dbo.qryTransactions (
   ID int IDENTITY (0,1) NOT NULL CONSTRAINT pk_qryTransactions PRIMARY KEY CLUSTERED,
   spid int NOT NULL,
   OrderID int,
   ItemID int,
   TimeTransactionStart datetime,
   TimeTransactionEnd datetime,
...other fields
   )

CREATE INDEX idx_qryTransactions_spidID ON qryTransactions (spid, ID) INCLUDE (ItemID, OrderID, TimeTransactionStart, TimeTransactionEnd)

比評論塊更雜亂無章……並且想要突出顯示OP為回應Ray的回答而做出的評論:

  • parent proc (Common_InsertOrders_1) 創建一個臨時表
  • 子 proc (InsertOrders) 查詢臨時表
  • 正在為子 proc (InsertOrders) 看到編譯鎖

稍微切線一分鐘……關於這種情況會發生什麼是Sybase ASE……

  • 每個臨時表都有一個唯一的對象 i​​d(當然,對象 id 可以在某些時候重複使用,但這種情況很少見,並發會話肯定不會發生)
  • 由於臨時表的對象 ID發生了變化, Sybase ASE 通常會在每次執行子 proc 時強制重新編譯
  • 如果 Sybase ASE 發現臨時表的結構在儲存的 proc 呼叫之間發生了變化(例如,不同的列數、不同的列名/數據類型/可空性),它也會強制重新編譯子 proc
  • 較新版本的 Sybase ASE 有一個配置(有效地)告訴編譯器忽略臨時表對象 ID 中的更改,從而消除了子 proc 的重新編譯(注意:如果表結構發生更改,仍然會發生重新編譯)

回到 OP 的問題(子程序上的編譯鎖定)……

  • 是否有可能 Sybase ASE 行為的一些痕跡仍然存在於 SQL Server 中(從這兩種產品是豆莢中的豌豆開始)?
  • 是否有任何 SQL Server 配置可以減少(消除?)子 proc 的重新編譯(如果由於對象 id 的更改)?
  • OP 可以驗證父 proc 是否每次都創建具有相同結構/DDL 的臨時表?

至於使用帶有@@SPID 的單個永久表來區分會話之間的行的想法……去過那裡,看到了……;反復出現的問題:

  • 如何/何時清理孤立行
  • 如果存在孤立數據(或在清理孤立數據期間,例如,刪除 @@SPID=10 但有一個新的/目前/活動會話與 @ @SPID=10 => 清理刪除了太多數據)
  • 從行鎖升級到頁/表鎖的可能性
  • 如果表有索引,那麼在更新索引時可能(b)鎖定
  • 根據表所在的數據庫,您可能會查看更多用於寫入日誌設備的活動(在 Sybase ASE 中,可以有效地禁用 tempdb 中的日誌記錄)
  • 甚至行級(獨占)鎖也可以阻塞其他會話(取決於隔離級別以及會話是否可以掃描過去/跳過所述獨占鎖)

我想回去(重新)調查根本問題(子程序上的重新編譯鎖),看看是否有辦法減少(消除?)所說的編譯鎖。

$$ Unfortunately my SQL Server knowledge on these issues is … NULL … so would be interested in input from some SQL Server compiler experts. $$

引用自:https://dba.stackexchange.com/questions/243115