情况如下。我们有两个数据库,我们使用我们要复制的表CPT
foreach表创建了一个异步复制系统。
所以每次都有一个表上的操作,例如(BATCH_COUNT
),一个触发器被调用,我们写入CPT
表(BATCH_COUNT_CPT
)我们做了什么操作哪排。服务读取该表并执行所请求的操作。
为了避免在表CPT
中多次插入,触发器检查是否已经有UPDATE
未处理,因此它没有插入新的更新,或者如果删除了,它删除该行的所有操作并插入删除。
ALTER TRIGGER [dbo].[BATCH_COUNT_CPT_TRIGGER]
ON [dbo].[BATCH_COUNT]
AFTER INSERT,UPDATE,DELETE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for trigger here
if((select UPPER(suser_name())) <> UPPER('XXXXXX\UEWIcptValService'))
begin
--------------------------DELETE----------------------------------------
if ((select count(*) from inserted) = 0 and (select count(*) from deleted) <> 0)
begin
DECLARE @CptId uniqueidentifier;
DECLARE deleteCursor CURSOR FAST_FORWARD FOR
SELECT CPT_ID FROM deleted
OPEN deleteCursor
FETCH NEXT FROM deleteCursor INTO @CptId
WHILE @@FETCH_STATUS = 0
BEGIN
if((select count(CPT_ID) from [BATCH_COUNT_CPT] where CPT_ID = @CptId and OPERATION = 'INSERT') <> 0)
Begin
DELETE FROM [NEWDOCS].[dbo].[BATCH_COUNT_CPT] WHERE CPT_ID = @CptId
End
ELSE
if((select count(CPT_ID) from [BATCH_COUNT_CPT] where CPT_ID = @CptId and OPERATION = 'UPDATE') <> 0)
Begin
DELETE FROM [NEWDOCS].[dbo].[BATCH_COUNT_CPT] WHERE CPT_ID = @CptId
INSERT INTO NEWDOCS.dbo.BATCH_COUNT_CPT (CPT_ID,OPERATION,[Date],[Skip]) VALUES (@CptId, 'DELETE',GetDate(),0)
End
ELSE
if((select count(CPT_ID) from [BATCH_COUNT_CPT] where CPT_ID = @CptId and OPERATION = 'DELETE') = 0)
Begin
INSERT INTO NEWDOCS.dbo.BATCH_COUNT_CPT (CPT_ID,OPERATION,[Date],[Skip]) VALUES (@CptId, 'DELETE',GetDate(),0)
End
FETCH NEXT FROM deleteCursor INTO @CptId
END
CLOSE deleteCursor
DEALLOCATE deleteCursor
end
--------------------------END DELETE----------------------------------------
--------------------------UPDATE--------------------------------------------
if ((select count(*) from inserted) <> 0 and (select count(*)from deleted) <> 0)
begin
--DECLARE @CptId uniqueidentifier;
DECLARE insertCursor CURSOR FAST_FORWARD FOR
SELECT CPT_ID FROM inserted
OPEN insertCursor
FETCH NEXT FROM insertCursor INTO @CptId
WHILE @@FETCH_STATUS = 0
BEGIN
---
if((select count(CPT_ID) from [BATCH_COUNT_CPT] where CPT_ID = @CptId and (OPERATION = 'INSERT' or OPERATION = 'UPDATE')) = 0)
Begin
INSERT INTO NEWDOCS.dbo.BATCH_COUNT_CPT (CPT_ID,OPERATION,[Date],[Skip]) VALUES (@CptId, 'UPDATE',GetDate(),0)
End
---
FETCH NEXT FROM insertCursor INTO @CptId
END
CLOSE insertCursor
DEALLOCATE insertCursor
end
--------------------------END UPDATE----------------------------------------
--------------------------INSERT--------------------------------------------
if ((select count(*) from inserted) <> 0 and (select count(*)from deleted) = 0)
begin
INSERT INTO NEWDOCS.dbo.BATCH_COUNT_CPT (CPT_ID,OPERATION,[Date],[Skip]) SELECT CPT_ID,'INSERT',GetDate(),0 FROM INSERTED;
end
--------------------------END INSERT----------------------------------------
end
END
所以问题是在触发器执行期间表BATCH_COUNT_CPT
没有被锁定。如果服务读取并删除它,可能会导致问题,并且某些操作将丢失。在执行整个触发器期间,我不知道如何在CPT
表上执行锁定。
我认为
select * from BATCH_COUNT_CPT (TABLOCK)
应该做的伎俩,但我不确定它是如何工作的。
如果它在整个交易过程中被锁定,或者只是在选择时被锁定,那也不是很有帮助。