SQL服务器 - 检查约束“不工作”

问题描述:

我有一个与SQL Server CHECK约束问题的问题“不工作”:SQL服务器 - 检查约束“不工作”

我们使用SQL Server 2012 Enterprise实例。我们有一个描述实体(实体是与FK不同的表)的事件和时间范围(开始时间,结束时间)的表格。

我们不允许在部分重叠的时间范围内的同一个实体上发生两个事件,为此我们在DB中添加了一个检查约束,在这种情况下应该失败。

这是检查约束功能:

CREATE FUNCTION [dbo].[DoesConflictingEventExist] 
(
    @existing_event_id int, 
    @entity_id bigint, 
    @start_time datetime, 
    @end_time datetime 
) 
RETURNS bit 
AS 
BEGIN 
    return case 
     when exists (select * from Events er1 
        where 
          er1.EntityId = @entity_id 
          and not (er1.EndTime <= @start_time 
            or @end_time <= er1.StartTime) 
          and er1.Id <> @existing_event_id) then 1 
     else 0 
    end 
END 

有时候,也许当大量并发负载的是在DB,不知何故事件记录与同entityId和重叠的时间内就设法得到添加到DB并且不会引发错误。

当我们运行上面的函数内的查询,它确实找到那些重复的事件......

这里是被添加到数据库重复的事件的例子:

Event1(id 2691604): 
entityID 8095119352335255831, starttime 2015-07-05 15:02:43.000 endtime 2016-06-30 13:28:41.000 
Event2(id 2691605): 
entityID 8095119352335255831, starttime 2015-07-05 15:03:19.000 endtime 2016-06-30 13:28:41.000 

我们考虑从检查约束切换到“而不是插入”触发器,因为检查约束被检查事实虽然记录已经在数据库中,但仍然 - 因为我们从约束没有得到任何错误,我们不确定是否我们不会看到与触发器相同的问题(如果它是并发/隔离问题,它可能不会消失)。

任何线索?

+0

在select语句中使用'ROWLOCK,UPDLOCK'可能会有所帮助 – Arvind

想象一下两笔交易同时做相同的:

  1. 插入冲突行
  2. 运行检查约束
  3. 提交

第2步没有看到其他事务未提交的行。

将检查约束函数的隔离级别提高到SERIALIZABLE,并确保查询计划触及少数行,以便少量数据被锁定。

+0

当然,请确保您的序列化查询不会锁定整个表! –