在不锁定sql server的情况下向上插入(更新或插入)

crcmnpdw  于 2021-07-24  发布在  Java
关注(0)|答案(0)|浏览(274)

我一直在读关于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更昂贵。你们怎么看?
谢谢!

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题