我正在使用SQL Server 2000,并且许多存储过程都广泛使用临时表.数据库有很多流量,我担心创建和删除临时表的线程安全性.
假设我有一个存储过程,它创建了一些临时表,它甚至可以将临时表连接到其他临时表等.还可以说两个用户同时执行存储过程.
是否有可能一个用户运行sp并创建一个名为#temp的临时表,另一个用户运行相同的sp但是因为数据库中已经存在一个名为#temp的表而被停止了?
如果同一个用户在同一个连接上执行两次相同的存储过程怎么样?
是否有任何其他奇怪的场景可能导致两个用户查询相互干扰?
casperOne.. 34
对于第一种情况,不可能,因为#temp是本地临时表,因此对其他连接不可见(假设您的用户使用单独的数据库连接).临时表名称别名为生成的随机名称,并在引用本地临时表时引用该名称.
在您的情况下,由于您要在存储过程中创建本地临时表,因此在退出过程范围时将删除该临时表(请参阅"备注部分").
对于第二种情况,是的,您将收到此错误,因为该表已存在,并且该表持续的时间与连接一样长.如果是这种情况,那么我建议您在尝试创建表之前检查表是否存在.
对于第一种情况,不可能,因为#temp是本地临时表,因此对其他连接不可见(假设您的用户使用单独的数据库连接).临时表名称别名为生成的随机名称,并在引用本地临时表时引用该名称.
在您的情况下,由于您要在存储过程中创建本地临时表,因此在退出过程范围时将删除该临时表(请参阅"备注部分").
对于第二种情况,是的,您将收到此错误,因为该表已存在,并且该表持续的时间与连接一样长.如果是这种情况,那么我建议您在尝试创建表之前检查表是否存在.
创建本地范围的临时表(带有一个#),在它们的末尾带有一个标识符,使它们成为唯一的; 多个呼叫者(即使使用相同的登录名)也不应重叠.
(尝试一下:从两个连接和相同的登录创建相同的临时表.然后查询tempdb.dbo.sysobjects以查看创建的实际表...)
本地临时表是线程安全的,因为它们只存在于当前上下文中.请不要将上下文与当前连接混淆(来自MSDN:"存储过程中创建的本地临时表在存储过程完成时自动删除"),同一连接可以安全地调用两次或多次创建的存储过程本地临时表(如#TMP
).
您可以通过从两个连接执行以下存储过程来测试此行为.此SP将等待30秒,因此我们可以确保两个线程将同时运行他们自己版本的#TMP表:
CREATE PROCEDURE myProc(@n INT) AS BEGIN RAISERROR('running with (%d)', 0, 1, @n); CREATE TABLE #TMP(n INT); INSERT #TMP VALUES(@n); INSERT #TMP VALUES(@n * 10); INSERT #TMP VALUES(@n * 100); WAITFOR DELAY '00:00:30'; SELECT * FROM #TMP; END;