如何在事务中的 SP 运行 中管理全局临时表?
How to manage global temporary tables in SP run inside transaction?
运行SQL Server 2014
。我有一个存储过程,我需要将数据写入全局临时 table。但是,当在事务内部调用过程时,方法 OBJECT_ID
似乎挂起。
如何在不删除事务的情况下解除死锁?
存储过程:
CREATE PROCEDURE [dbo].[foo]
@Data [varbinary](max)
WITH ENCRYPTION AS
BEGIN
SET NOCOUNT ON
IF OBJECT_ID('tempdb..##TempData') IS NULL
CREATE TABLE ##TempData
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Data] [int] NOT NULL UNIQUE
)
INSERT INTO ##TempData ([Data]) SELECT @Data
END
GO
第一次连接:
BEGIN TRAN
EXEC [foo] @Data = 1
WAITFOR DELAY '00:00:20'
COMMIT TRAN
DROP TABLE ##TempData
然后在第二个连接中:
BEGIN TRAN
EXEC [foo] @Data = 2 -- This will hang on the call to OBJECT_ID()...
COMMIT TRAN
更新
下面是一些 C#
代码,说明了为什么我需要进行交易。
var options = new TransactionOptions();
// options.IsolationLevel = IsolationLevel.ReadCommitted;
options.Timeout = TransactionManager.MaximumTimeout;
using (var transaction = new TransactionScope(TransactionScopeOption.Required, options))
{
// Write to ##TempData. Lengthy operation...
var foo = Foo(data);
// These two MUST be inside a transaction!
var bar = Bar();
var baz = Baz(); // Consume data in ##TempData
transaction.Complete();
}
(希望这将是解决您的问题的另一种潜在方法...评论时间太长)
除了评论中的内容之外,我相信使用实际的 table 可能会让你更轻松地做你想做的事情(虽然我有点不清楚关于那是什么)
如果您以这种方式创建 table:
create table tmpDataThingy (
connectionUniqueId uniqueIdentifier,
someOtherColumn int,
andYetAnother varchar(50)
)
以这种方式创建 table(重要部分是 connectionUniqueId
)将允许您在操作数据时跟踪 "Units of work"(可能不是正确的词) table.
您的 using 语句可能更像这样:
using (var transaction = new TransactionScope(TransactionScopeOption.Required, options))
{
Guid uniqueId = Guid.NewGuid(); // consider this a "session" identifier for a single instance of the work needed for this call
// insert your data into tmpDataThingy ensuring connectionUniqueId = uniqueId (the guid created above)
// consume/manipulate data in tmpDataThingy only for the specified uniqueId
// remove data from tmpDataThingy for the uniqueId
transaction.Complete();
}
执行上述操作后,您将不会遇到 table 不存在的潜在问题,由于每次调用函数时生成的 uniqueId 不同,多个用户调用具有冲突数据的同一函数的可能性也不大等
运行SQL Server 2014
。我有一个存储过程,我需要将数据写入全局临时 table。但是,当在事务内部调用过程时,方法 OBJECT_ID
似乎挂起。
如何在不删除事务的情况下解除死锁?
存储过程:
CREATE PROCEDURE [dbo].[foo]
@Data [varbinary](max)
WITH ENCRYPTION AS
BEGIN
SET NOCOUNT ON
IF OBJECT_ID('tempdb..##TempData') IS NULL
CREATE TABLE ##TempData
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Data] [int] NOT NULL UNIQUE
)
INSERT INTO ##TempData ([Data]) SELECT @Data
END
GO
第一次连接:
BEGIN TRAN
EXEC [foo] @Data = 1
WAITFOR DELAY '00:00:20'
COMMIT TRAN
DROP TABLE ##TempData
然后在第二个连接中:
BEGIN TRAN
EXEC [foo] @Data = 2 -- This will hang on the call to OBJECT_ID()...
COMMIT TRAN
更新
下面是一些 C#
代码,说明了为什么我需要进行交易。
var options = new TransactionOptions();
// options.IsolationLevel = IsolationLevel.ReadCommitted;
options.Timeout = TransactionManager.MaximumTimeout;
using (var transaction = new TransactionScope(TransactionScopeOption.Required, options))
{
// Write to ##TempData. Lengthy operation...
var foo = Foo(data);
// These two MUST be inside a transaction!
var bar = Bar();
var baz = Baz(); // Consume data in ##TempData
transaction.Complete();
}
(希望这将是解决您的问题的另一种潜在方法...评论时间太长)
除了评论中的内容之外,我相信使用实际的 table 可能会让你更轻松地做你想做的事情(虽然我有点不清楚关于那是什么)
如果您以这种方式创建 table:
create table tmpDataThingy (
connectionUniqueId uniqueIdentifier,
someOtherColumn int,
andYetAnother varchar(50)
)
以这种方式创建 table(重要部分是 connectionUniqueId
)将允许您在操作数据时跟踪 "Units of work"(可能不是正确的词) table.
您的 using 语句可能更像这样:
using (var transaction = new TransactionScope(TransactionScopeOption.Required, options))
{
Guid uniqueId = Guid.NewGuid(); // consider this a "session" identifier for a single instance of the work needed for this call
// insert your data into tmpDataThingy ensuring connectionUniqueId = uniqueId (the guid created above)
// consume/manipulate data in tmpDataThingy only for the specified uniqueId
// remove data from tmpDataThingy for the uniqueId
transaction.Complete();
}
执行上述操作后,您将不会遇到 table 不存在的潜在问题,由于每次调用函数时生成的 uniqueId 不同,多个用户调用具有冲突数据的同一函数的可能性也不大等