究竟何时多个用户无法同时运行带有临时表的存储过程?

Wes*_*all 9 sql-server stored-procedures temporary-tables

我有一个关于我最近在TechNet 上阅读的有关临时表的文档的问题。该页临时表部分的第四段内容如下:

如果使用命名约束创建临时表,并且临时表是在用户定义的事务范围内创建的,则一次只有一个用户可以执行创建临时表的语句。例如,如果一个存储过程创建了一个带有命名主键约束的临时表,则该存储过程不能被多个用户同时执行。

我在这样一个环境中工作,在这种环境中,我们大量使用了一些使用索引临时表的存储过程,而且我们从未遇到过用户必须等待一次执行完成才能开始下一次执行的问题。我希望情况会继续如此,但我担心如果没有正确理解这个警告,它可能会成为一个问题。

具体来说,我不清楚以下几点:

  1. 这仅适用于全局临时表,还是也适用于本地临时表?在会话之外不可见的表(如后一种情况)会阻止另一个会话同时执行,这似乎很奇怪。
  2. 什么是“命名约束”?不是所有的约束都有名字吗(即使它们是系统生成的)?这是指具有用户定义别名的约束吗?这对我来说似乎是糟糕的措辞。
  3. “多个用户”实际上意味着多个会话吗?这些过程是通过我们的应用程序使用单个服务帐户调用的,因此对我们脚本的 99.9% 的调用是由该单个帐户对数据库进行的(而且我不关心管理员偶尔会在后端进行调用)。如果服务帐户可以同时在多个会话中运行 sproc,那么这个问题对我来说没有意义。

Eri*_*ing 11

这适用于本地临时表。

命名约束和未命名约束的区别在于:

CREATE TABLE #t1 (c1 INT PRIMARY KEY CLUSTERED)

CREATE TABLE #t2 (c1 INT,
                     CONSTRAINT pk_c1 PRIMARY KEY  CLUSTERED(c1) )
Run Code Online (Sandbox Code Playgroud)

让系统名称约束使得发生冲突的可能性极小。在此示例中,如果您在 SSMS 中打开两个窗口,您将能够在两个窗口中创建#t1,但不能在#t2.

全局临时表由所有用户共享,因此您必须以不同的方式处理事情。在使用它们的最后一个会话完成之前,它们不会被“破坏”,因此您需要确保当用户访问它们时,他们只能访问他们的数据。这有时由 SPID 完成,有时由散列值完成。这取决于如何使用全局临时表。

通常,对于全局临时表,存储过程将检查如果它们存在,然后只创建它们如果OBJECT_ID()NULL

多个用户意味着多个会话。登录名与它无关。如果 George 运行sp_something @i = 1并且 Gina 运行sp_something @i = 2,则它们是否都以 身份登录并不重要User1,它们将具有不同的 SPID。


Joe*_*ish 10

我认为这是因为您不能在tempdb.sys.key_constraints. 这是我的一台服务器上的元数据视图中的内容:

初步看法

所有以 结尾的奇怪名称_6E...都是 SQL Server 自动生成的名称。它们不是命名约束,因为我在创建它们时没有明确给它们命名。SQL Server 在幕后生成一个约束名称,理论上可以避免名称冲突。

如果我尝试在两个不同的会话中创建下表:

create table #x1 (
ID INT NOT NULL,
CONSTRAINT NAMED_CONSTRAINT_1 PRIMARY KEY (ID)
);
Run Code Online (Sandbox Code Playgroud)

第二个运行的会抛出一个错误:

Msg 2714, Level 16, State 5, Line 1

数据库中已经有一个名为“NAMED_CONSTRAINT_1”的对象。

消息 1750,级别 16,状态 1,第 1 行

无法创建约束或索引。请参阅以前的错误。

再次检查视图:

有约束

如果我尝试在两个会话中创建下表,则没有问题:

create table #y1 (
ID INT NOT NULL,
PRIMARY KEY (ID)
);
Run Code Online (Sandbox Code Playgroud)

这是元数据视图:

使用默认约束

只是直接回答您的问题:您引用的部分适用于本地和全局临时表,命名约束是您故意为其命名的约束,多个用户意味着多个会话。