我想保持我的Azure的SQL Server数据库中数据的一致性,实现了两种方案,以保持数据的一致性:天青时SQL Server无法使用检查约束和触发
- 检查约束
- 插入/更新触发器
没有一个能够工作,而且当我的支票被绕过时,我仍然能够重现这种情况。规则很简单 - there couldn't be more than one active assignment for a user
。
Tasks:
- Id
- UserId
- Status ('Active', 'Done')
User
- Id
- ...
方法#1 - Check Constraints
我已经实现的功能,以确保数据的一致性和应用它作为一个检查约束
create function [dbo].[fnCheckUserConcurrentAssignment]
(
@id nvarchar(128),
@status nvarchar(50), -- not used but required to check constraint
)
returns bit
as
begin
declare @result bit
select @result = cast(case when (select count(t.Id)
from dbo.Tasks t
where t.[UserId] = @id
and t.[Status != 'Done') > 1
then 1
else 0
end as bit)
return @result
end
alter table dbo.Tasks
with check add constraint [CK_CheckUserConcurrentAssignment]
check (dbo.fnCheckUserConcurrentAssignment([UserId], [Status]) = 0)
方法#2 - Trigger
alter trigger dbo.[TR_CheckUserConcurrentAssignment]
on dbo.Tasks
for insert, update
as begin
if(exists(select conflictId from
(select (select top 1 t.Id from dbo.Tasks t
where t.UserId = i.UserId
and o.[Status] != N'Done'
and o.Id != i.Id) as conflictId
from inserted i
where i.UserId is not null) conflicts
where conflictId is not null))
begin
raiserror ('Concurrent user assignment detected.', 16, 1);
rollback;
end
end
如果我并行创建大量任务(regularl y> 10),那么其中的一些将被约束/触发器拒绝,其他将能够同时将UserId保存在数据库中。因此数据库数据会不一致。
我已经在Management Studio中验证了这两种方法,它可以防止我破坏我的数据。我无法将多个“活动”任务分配给给定的用户。
什么是improtant说,我用Entity Framework 6.x
在我的后端,以节省我的数据(SaveChangesAsync
)和每一个动作都是在单独的事务用默认事务隔离级别执行保存ReadCommited
什么可能是错误的我的方法以及如何保持我的数据一致?
的作品,这是一个惊喜,我检查约束也受到竞争条件。对我而言,这是一个独特的索引。在我的情况下,我没有义务使用函数或触发器,并且我的条件很简单,所以我使用唯一的过滤索引并且它可以工作。现在我的代码中仍然有例外,但只要数据始终保持一致,就可以很好地处理它们。谢谢! –
实际上,对函数的检查约束变为由两个(或更多步骤)组成的非原子操作。你的函数和触发它的语句('INSERT'或'UPDATE')在相同的事务隔离级别下运行。发动机周围没有“魔法”可以防止竞赛状况。当涉及到独特的(过滤)索引时,引擎具有“魔力”,即使在高并发负载下也能确保索引保持唯一。 –
如果你想进一步研究这个话题,我建议搜索'检查约束udf'。例如:http://dba.stackexchange.com/questions/12779/how-are-my-sql-server-constraints-being-bypassed http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/07/ 01/when-check-constraints-using-udfs-fail-for-multirow-updates.aspx http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/06/25/scalar-udfs-wrapped-in-check -constraints-is-very-slow-and-may-fail-for-multirow-updates.aspx https://www.brentozar.com/archive/2016/04/another-hidden-parallelism-killer-scalar-udfs-检查约束/ –