我有一个来自应用程序的复杂工作单元,它可能将更改作为单个事务提交到 10-15 个表。工作单元在快照隔离下执行。
一些表有一个触发器,它执行存储过程以将消息记录到队列中。该消息包含表名称、键和更改类型。这是提供与 SQL2005 的向后兼容性所必需的,我不能使用内置队列。
问题是我在队列写入存储过程中遇到阻塞和超时。我要么收到一条消息说:
Snapshot isolation transaction aborted due to update conflict. You cannot use snapshot isolation to access table 'dbo.tblObjectChanges' directly or indirectly in database
或者我在写入该表时超时。
有没有办法从触发器中更改对(或在其中)执行消息队列写入的存储过程的特定调用的事务隔离?作为最后的手段,我可以对存储过程的删除或更新部分进行异步调用吗?
这是存储过程的 SQL:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[usp_NotifyObjectChanges]
@ObjectType varchar(20),
@ObjectKey int,
@Level int,
@InstanceGUID varchar(50),
@ChangeType int = 2
AS
SET NOCOUNT ON
DECLARE @ObjectChangeID int
--Clean up any messages older than 10 minutes
DELETE from tblObjectChanges Where CreatedTime < DATEADD(MINUTE, -10, GetDate())
--If the object is already in the queue, change the time and instanceID
SELECT @ObjectChangeID = [ObjectChangeID] FROM tblObjectChanges WHERE [ObjectType] = @ObjectType AND [ObjectKey] = @ObjectKey AND [Level] = @Level
IF NOT @ObjectChangeID is NULL
BEGIN
UPDATE [dbo].[tblObjectChanges] SET
[CreatedTime] = GETDATE(), InstanceGUID = @InstanceGUID
WHERE
[ObjectChangeID] = @ObjectChangeID
END
ELSE
BEGIN
INSERT INTO [dbo].[tblObjectChanges] (
[CreatedTime],
[ObjectType],
[ObjectKey],
[Level],
ChangeType,
InstanceGUID
) VALUES (
GETDATE(),
@ObjectType,
@ObjectKey,
@Level,
@ChangeType,
@InstanceGUID
)
END
tblObjectChanges 的定义:
CREATE TABLE [dbo].[tblObjectChanges](
[CreatedTime] [datetime] NOT NULL,
[ObjectType] [varchar](20) NOT NULL,
[ObjectKey] [int] NOT NULL,
[Rowversion] [timestamp] NOT NULL,
[Level] [int] NOT NULL,
[ObjectChangeID] [int] IDENTITY(1,1) NOT NULL,
[InstanceGUID] [varchar](50) NULL,
[ChangeType] [int] NOT NULL,
CONSTRAINT [PK_tblObjectChanges] PRIMARY KEY CLUSTERED
(
[ObjectChangeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
GO