简体   繁体   English

通过并发检查SQL Server升级

[英]Upsert with concurrency checking SQL Server

I have a system in production that I need to retrofit with concurrency checking due to increased use and some issues that have arisen. 由于使用量增加和出现了一些问题,我的生产系统需要对并发检查进行改进。

Currently I'm using stored procedures that follow a basic upsert pattern: 目前,我正在使用遵循基本upsert模式的存储过程:

Update X where key = @key 
if @@rowcount = 0
Insert into... 

Into that mix I need to check for row changes. 进入这种混合中,我需要检查行更改。 I plan on using a Rowversion/Timestamp. 我计划使用Rowversion / Timestamp。

I don't want to just add: 我不想只添加:

Update ...  Where key = @key AND Row_Version = @Row_Version 

I want to fire a SQL error or something that can be caught by C# so that I can communicate the concurrency issue to the user, rather than just do nothing or a more "generic" error. 我想触发一个SQL错误或C#可能捕获的错误,以便我可以将并发问题传达给用户,而不是什么也不做或更多的“一般”错误。

So, I think I'm going to have to ditch my Upsert and do things as follows: 因此,我认为我将不得不放弃我的Upsert并执行以下操作:

-- Update Check
if exists (select @Current_Row_Version from table where key = @key)
    if @Current_Row_Version != @Row_Version 

        RAISEERROR('Concurrency Violation - TableName', 11,1);            
        Return
    else
        Update * set...  Where Key = @key

else
    -- Insert
    insert ... 

So, does that look like I'm the right track? 那么,这看起来像我的正确轨道吗? Are there better patterns or practices? 有更好的模式或做法吗?

Found some interesting examples such as here but nothing that quite fits my need. 找到了一些有趣的示例,例如此处,但没有一个完全符合我的需求。 I could try the insert first as here but I think I'm going to be doing more updating than inserting. 我可以在这里先尝试插入,但是我想我将比插入做更多的更新。

Merge will not work for me either. 合并对我也不起作用。

This Update/Insert will be part of a transaction as well... if any part fails, I need to roll everything back. 此更新/插入也将是事务的一部分...如果任何部分失败,我需要回滚所有内容。 The rollback is handled in C# code based on errors caught. 根据捕获的错误,使用C#代码处理回滚。

To ensure the that the row doesn't change between your if and your update , you could specify the locking hints updlock and holdlock : 为了确保在ifupdate之间行不会改变,可以指定锁定提示 updlockholdlock

begin transaction;
if exists (select @Current_Row_Version from table with (updlock, holdlock) where key=@key)
    begin
    if @Current_Row_Version != @Row_Version 
        begin
        rollback transaction;
        raiserror ('Concurrency Violation - TableName', 11,1);            
        return
        end
    else
        update * set...  Where Key = @key
    end
commit transaction;

Note that raiserror is written with one E . 请注意, raiserror用一个E编写

A more common way to do optimistic locking is : 进行乐观锁定的更常见方法是:

update   ...
set      ...
where    row_version = @target_row_version

And then check the number of updated rows client side. 然后检查客户端的更新行数。 If it's 0, your optimistic update has failed. 如果为0,则您的乐观更新失败。

For more information on SQL Server's concurrency support read the MSDN pages for set transaction isolation level . 有关SQL Server并发支持的更多信息,请阅读MSDN页面以设置事务隔离级别

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM