Sql-Server
在 DB 表中使用 SPID(而不是表變數)
用於預訂事物的事務數據庫…
我們的供應商被要求用@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……
- 每個臨時表都有一個唯一的對象 id(當然,對象 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. $$