我一直在读关于upsert的可能解决方案。特别是,这里的这个线程,upsert的解决方案是:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
UPDATE dbo.table SET ... WHERE PK = @PK;
IF @@ROWCOUNT = 0
BEGIN
INSERT dbo.table(PK, ...)
END
COMMIT TRANSACTION;
但是,由于隔离级别可序列化,我将在表级别引入锁,对吗?这并不理想,因为使用upsert可能会对该表执行很多操作。
我认为我们首先引入了隔离级别serializable,以防止两个并发事务试图更新同一条不存在的记录,然后其中一个事务将无法插入该记录。但是,我正在考虑执行以下操作来解决没有锁的问题:
BEGIN TRANSACTION;
UPDATE dbo.table SET ... WHERE PK = @PK;
IF @@ROWCOUNT = 0
BEGIN
BEGIN TRY
INSERT dbo.table(PK, ...)
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 2627
BEGIN
UPDATE dbo.table SET ... WHERE PK = @PK;
END
END CATCH
END
COMMIT TRANSACTION;
在这种情况下,如果插入失败,则意味着同时有其他并发事务插入了一行。然后,我们再做一次更新。
然而,我担心的是错误处理是否比使用serializable更昂贵。你们怎么看?
谢谢!
暂无答案!
目前还没有任何答案,快来回答吧!