我想保持我的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-檢查約束/ –