Sql server 事务递增重复记录名称

Sql server 事务递增重复记录名称,sql-server,transactions,Sql Server,Transactions,我会尽力把这个问题说清楚。给定此基本对象和表架构: 文件 名称::字符串 我有一个设计规范,类似于: 给定用户, 当我创建一个新的文档时, 并且Document.Name不是唯一的, 然后在文档中添加“(n)”。Name通过查找最高的重复索引:n,并将n增加1。如果不存在重复项,则n初始化为2。 ``` 例子 新文档 新文件(2) 新文件(3) 这看起来应该很熟悉-类似于文件系统的行为。但是,我在处理此事务的可伸缩性方面遇到了问题 控制流 邮寄文件 开始事务重新提交 GetSimilarDoc

我会尽力把这个问题说清楚。给定此基本对象和表架构:

文件 名称::字符串

我有一个设计规范,类似于:

给定用户,
当我创建一个新的
文档时,
并且
Document.Name
不是唯一的,
然后
文档中添加“(n)”。Name
通过查找最高的重复索引:n,并将n增加1。如果不存在重复项,则n初始化为2。 ```

例子 新文档
新文件(2)
新文件(3)

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

控制流 邮寄文件

开始事务重新提交

GetSimilarDocumentNames(即“{Document.Name}%”)

ProcessNameForDuplication

插入文件

提交事务

返回文件

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

  • 使用C#锁定无法跨多个web头工作
  • 更改为ReadUncommitted不会有帮助,因为请求1必须在请求2查询类似文档名称之前完成Insert
似乎我们需要结合使用表锁,将此业务逻辑深入到SQL中。是否有其他可能的解决办法不需要这种限制性措施

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

  • 如果由于两个进程在调用“Insert Document”之前调用“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
    
    为了防止两个进程添加同一文档,处理重复的行错误情况应该有所帮助,或者将隔离级别更改为SERIALIZABLE(),这将锁定表,直到添加文档为止