out*_*jet 8 sql-server stored-procedures sql-server-2016 enterprise-edition table-variable
用于预订事物的事务性数据库...
我们的供应商被要求用@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)
Run Code Online (Sandbox Code Playgroud)
在我看来,使用@@SPID
类似的方法是在自找麻烦。
会话 ID 经常被重用;一旦用户连接注销,该会话 ID 就可以再次使用,并且很可能被下一个尝试连接的会话使用。
为了使其至少半可靠地工作,您需要一个登录触发器来清除表中具有相同@@SPID
. 如果这样做,您可能会看到使用该@@SPID
列对表进行了大量锁定。
SQL Server 确实使用行锁定,但它也使用页锁定和表锁定。当然,您可以通过良好的索引来缓解这种情况,但这对我来说仍然是一种反模式。
如果存储过程是用于访问受影响表的唯一方法,您可以调查使用应用程序锁,通过sp_getapplock
基本上序列化对相关部分的访问。sp_getapplock 的文档在这里。 Erik Darling有一篇关于它的有趣帖子在这里。
比评论块更杂乱无章......并且想要突出显示OP针对Ray的回答所做的评论:
稍微切线一分钟......在这种情况下会发生什么是Sybase ASE......
回到OP的问题(子进程上的编译锁)......
至于使用带有@@SPID 的单个永久表来区分会话之间的行的想法......去过那里,看到...... yuck ; 反复出现的问题:
我想回去(重新)调查根本问题(子进程上的重新编译锁),看看是否有办法减少(消除?)所说的编译锁。[不幸的是,我在这些问题上的 SQL Server 知识是...... NULL ...所以会对一些 SQL Server 编译器专家的输入感兴趣。]