Sql server SQL Server合并命令重复pk错误

Sql server SQL Server合并命令重复pk错误,sql-server,tsql,Sql Server,Tsql,如果事务同时发生,此存储过程通常会失败,因为它违反了对重复键(字段、名称)的pk约束。我一直在尝试holdlock、rowlock和begin/commit事务,这导致了相同的错误 我正在尝试执行一个insert语句,如果该记录使用相同的键(字段、名称)存在,则更新它 性能很重要,所以我试图避免使用临时表解决方案 MERGE Fielddata AS TARGET USING (VALUES (@Field, @Name, @Value, @File, @Type)) AS SOURCE

如果事务同时发生,此存储过程通常会失败,因为它违反了对重复键(字段、名称)的pk约束。我一直在尝试holdlock、rowlock和begin/commit事务,这导致了相同的错误

我正在尝试执行一个insert语句,如果该记录使用相同的键(字段、名称)存在,则更新它

性能很重要,所以我试图避免使用临时表解决方案

MERGE Fielddata AS TARGET
USING (VALUES (@Field, @Name, @Value, @File, @Type))
    AS SOURCE (Field, Name, Value, File, Type)
    ON TARGET.Field = @Field AND TARGET.Name = @Name
WHEN MATCHED THEN
    UPDATE
    SET Value = SOURCE.Value,
        File = SOURCE.File,
        Type = SOURCE.Type
WHEN NOT MATCHED THEN
    INSERT (Field, Name, Value, File, Type)
    VALUES (SOURCE.Field, SOURCE.Name, SOURCE.Value, SOURCE.File, SOURCE.Type);
编辑:使用serializable/holdlock测试24小时。30分钟后:无错误


编辑2:
WITH(SERIALIZABLE)
/
设置事务隔离级别SERIALIZABLE
有效地解决了重复密钥问题,在我们的案例/场景中会降低一点性能。

您必须提高事务隔离级别。 将事务隔离级别设置为可序列化

SERIALIZABLE指定以下内容:+语句无法读取数据 已修改但尚未由其他事务提交的。不 其他事务可以修改当前用户已读取的数据 直到当前事务完成其他 事务不能插入键值为的新行 当前事务中任何语句读取的键的范围 直到当前事务完成。范围锁放置在 与每条语句的搜索条件匹配的键值范围 在事务中执行。这将阻止其他事务从 更新或插入任何符合以下条件的行: 由当前事务执行的语句。这意味着如果有 如果事务中的语句第二次执行,则 将读取同一组行。档位锁一直保持到 事务完成。这是最严格的隔离 级别,因为它锁定整个范围的钥匙并保持锁 直到事务完成。因为并发性较低,所以使用 仅在必要时使用此选项此选项的效果与 在数据库中所有SELECT语句中的所有表上设置HOLDLOCK 交易。

可序列化实现

SQL Server碰巧使用了可序列化的锁定实现 隔离级别,获取物理锁并将其保持到底 事务(因此不推荐使用的表提示HOLDLOCK作为 可序列化的同义词)

这一战略还不足以提供技术保障 完全序列化,因为新的或更改的数据可能出现在 事务以前处理的行的范围。这 并发现象称为幻象,可能导致 不可能在任何连续计划中发生的影响

为确保针对虚拟并发现象提供保护,请锁定 SQL Server在可序列化隔离级别上采取的 合并键范围锁定,以防止新的或更改的行 出现在先前检查的索引键值之间。射程锁 并非总是在可序列化隔离级别下获取;所有我们 一般来说,可以说SQL Server总是获得足够的锁 以满足可序列化隔离级别的逻辑要求。 事实上,锁定实现通常会获得更多 比保证可序列化性所需的锁更严格, 但我离题了


如果很简单:它不仅阻塞源,而且阻塞插入范围

您必须提高事务隔离级别。 将事务隔离级别设置为可序列化

SERIALIZABLE指定以下内容:+语句无法读取数据 已修改但尚未由其他事务提交的。不 其他事务可以修改当前用户已读取的数据 直到当前事务完成其他 事务不能插入键值为的新行 当前事务中任何语句读取的键的范围 直到当前事务完成。范围锁放置在 与每条语句的搜索条件匹配的键值范围 在事务中执行。这将阻止其他事务从 更新或插入任何符合以下条件的行: 由当前事务执行的语句。这意味着如果有 如果事务中的语句第二次执行,则 将读取同一组行。档位锁一直保持到 事务完成。这是最严格的隔离 级别,因为它锁定整个范围的钥匙并保持锁 直到事务完成。因为并发性较低,所以使用 仅在必要时使用此选项此选项的效果与 在数据库中所有SELECT语句中的所有表上设置HOLDLOCK 交易。

可序列化实现

SQL Server碰巧使用了可序列化的锁定实现 隔离级别,获取物理锁并将其保持到底 事务(因此不推荐使用的表提示HOLDLOCK作为 可序列化的同义词)

这一战略还不足以提供技术保障 完全序列化,因为新的或更改的数据可能出现在 事务以前处理的行的范围。这 并发现象称为幻象,可能导致 不可能在任何连续计划中发生的影响

为确保针对虚拟并发现象提供保护,请锁定 SQL Server在可序列化隔离级别上采取的 合并键范围锁定,以防止新的或更改的行 出现在先前检查的索引键值之间。射程锁 并非总是在可序列化隔离级别下获取;所有我们 可以用g表示