此 API 端点使用“如果不存在则创建”sql 来保留用户的“喜欢”:
if not exists(
select 1 from likes
where UserId = @UserId and EntityId = @EntityId and EntityType = @EntityType)
insert into likes (UserId, EntityType, EntityId)
values (@UserId, @EntityType, @EntityId)
Likes 表没有 Id 列,而是具有由以下方式定义的主键:(UserId、EntityType、EntityId)。
它按预期工作...我已经通过 1) 直接查询数据库和 2) 通过部署的 API 对此进行了测试,并且它按预期工作。如果类似的已经存在,数据库将保持完全相同。
但是,我最近遇到了这个错误:
违反主键约束“PK_Likes”。无法插入 对象“dbo.Likes”中存在重复键。重复的键值为 (19, 1, 113)。该声明已终止。
我还要提到服务器正在运行 Azure Sql。
我无法重现此错误。请帮助我理解这是如何发生的。
谢谢你。
这是一个经典的竞争条件,“检查然后执行”。考虑一下如果两个数据库连接尝试在大致相同的时间执行相同的操作会发生什么。
连接A | 连接 B |
---|---|
如果不存在... | |
如果不存在... | |
真实 | |
真实 | |
插入... | |
插入... | |
成功 | |
重复 |
为了避免这种情况,“先检查再检查”。执行插入并捕获重复键错误。