以交互方式递增重复记录名称

时间:2015-02-08 00:35:48

标签: sql-server transactions

我会尽力表达这个问题。给定这个基本对象和表模式:

  

文档

     

Name :: string

我的设计规范如下:

鉴于用户,
何时我创建了一个新的Document
Document.Name不是唯一的,
然后追加" (N)"通过找到最高重复索引:到Document.Name,并将n递增1。如果还没有重复项,则n初始化为2。 ```

实施例

新文件
新文件(2)
新文件(3)
...

这看起来应该非常熟悉 - 类似于文件系统的行为方式。但是,我在处理此事务的可伸缩性方面遇到了问题。

控制流程

  

POST文件

     
    

开始交易ReadCommitted

         
      

GetSimilarDocumentNames(即" {Document.Name}%")

             

ProcessNameForDuplication

             

插入文件

    
         

提交交易

  
     

退回文件

不幸的是,在并行请求下这不起作用,很明显我们需要某种锁定机制。

  • 使用C#锁定不会在多个网站上工作。
  • 更改为ReadUncommitted不会有帮助,因为请求1必须在请求2查询类似文档名称之前完成插入。

似乎我们需要将这种业务逻辑更深入地推入SQL并结合使用表锁。是否有其他可能的解决方案不需要这种限制性措施?

  1. 如果使用了插入后触发器,我假设它们没有排队但是立即运行,因此仍然必须进行某种锁定?

1 个答案:

答案 0 :(得分:0)

如果您获得重复的数字,因为2个进程在同时调用#34; ProcessNameForDuplication"在它们都没有调用"插入文档"之前,有这样的表/功能应该有帮助

declare @DocNo int

begin tran

update
  Document
set
  @DocNo = DocNo,
  DocNo = DocNo + 1
where
  Name = @DocName

if (@@rowcount = 0) begin
  insert into Document values (@DocName, 2)
  set @DocNo = 1
end

commit

为了防止2个进程添加同一个文档,处理重复行错误的情况应该有所帮助,或者将隔离级别更改为SERIALIZABLE(https://msdn.microsoft.com/en-us/library/ms173763.aspx),这应该锁定表,直到添加文档为止。