我是否可以牺牲一致性以允许并发"插入或更新"以及使用SQL Server读取对单个表的访问权限?

Col*_*nee 3 sql t-sql sql-server

我有一个包含两列的表:一个资源键,以及(非常粗略地)上次访问它时.

我有许多服务器定期转储有关对表的资源访问的数据.如果资源密钥已经存在,它们应该更新资源密钥的访问时间,如果不存在,则应该插入它.

另一台服务器很少从该表生成报告.

我不要求此表保持一致.我很好,报告服务器在转储过程中读取表格.如果两个写入服务器尝试更新同一行,我不关心哪个获取它的数据.

有两个主要问题:

  1. 我正在寻找甚至可能与SQL Server?
  2. 如果可能的话,我可能会让多个服务器竞争"插入或更新"并导致主键约束违规.有什么方法可以解决这个问题吗?

Sol*_*zky 9

我很好,报告服务器在转储中读取表格.

查看READ COMMITTED SNAPSHOT ISOLATION选项.这是在SQL Server 2005中引入的,似乎可用于所有版本.它通常比使用WITH (NOLOCK)表提示更好.有关更多信息,请查看:

如果两个写入服务器尝试更新同一行,我不关心哪个获取它的数据.

两个操作不可能同时写入同一行.一个人会等

关于两个试图同时插入相同的值,因为你不关心哪一个"赢",只是陷阱并丢弃错误;-).

也许有些东西:

BEGIN TRY
  UPDATE tbl
  SET    tbl.AccessTime = GETDATE()
  FROM   SchemaName.TableName tbl
  WHERE  tbl.ResourceKey = @ResourceKey;

  IF (@@ROWCOUNT = 0)
  BEGIN
    INSERT INTO SchemaName.TableName (ResourceKey, AccessTime)
    VALUES (@ResourceKey, GETDATE());
  END;
END TRY
BEGIN CATCH
  IF (ERROR_NUMBER() <> 2627) -- 2627 = Violation of PRIMARY KEY constraint
  BEGIN
    ;THROW;
  END;
END CATCH;
Run Code Online (Sandbox Code Playgroud)

如果您使用的是SQL Server 2014(或者更新,只要发生这种情况),那么您可以查看使用:

  • @Jack但它不是*单一的原子操作*,除非你强制它使用高架隔离.啊,也有更糟糕的问题.请阅读[this post](http://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/).我实际上说服了我们所有的客户,以避免"MERGE",甚至在因为这些问题而被使用的几个地方将其淘汰. (2认同)