lad*_*dge 8 sql-server-2008 sql-server
我们在我们的数据库中发现了一些违反活动约束的行。这怎么可能?
约束处于活动状态,因为我们不能手动添加绕过此约束的行。但是,当我们运行 时CHECKCONSTRAINTS(Files),我们发现它在我们的测试运行期间有几次被绕过了。有问题的行都是在半秒内创建的,表明存在某种竞争条件。
这是应用于表的约束。该规则旨在确保给定父文件夹中的名称唯一性:
ALTER TABLE Files ADD CONSTRAINT UniqueNameInParentFolder CHECK
CheckUniqueNameInFolder(ParentFoldersID, Name) = 1;
Run Code Online (Sandbox Code Playgroud)
此约束调用如下所示的函数:
-- first check for the new name in the Folders table
IF ((SELECT COUNT(*) FROM Folders
WHERE ParentFoldersID = @FoldersID AND Name = @Name) = 0)
BEGIN
-- then check for it in the Files table
IF ((SELECT COUNT(*) FROM Files
WHERE ParentFoldersID = @FoldersID AND Name = @Name) <= 1)
RETURN 1
END
RETURN 0
Run Code Online (Sandbox Code Playgroud)
在事务中添加了单独的行,所以我很难理解重复的行是如何绕过这个限制的。
gbn*_*gbn 20
基于 UDF 的检查约束是垃圾。并发、RBAR、隔离等,如您所见。一些链接:
包裹在 CHECK 约束中的标量 UDF 非常慢,并且可能会因Alex Kuznetsov 的多行更新而失败
在检查约束中使用 UDF 来检查历史窗口(开始-结束日期窗口)的有效性,作者是 Tony Rogerson
在这种情况下,SQL Server 最安全的方法是使用标准约束,例如唯一键和外键。我不明白为什么你检查文件夹表中文件表的约束。
为了防止文件和文件夹只在给定的父文件夹中具有相同名称,请使用索引视图。重复文件或重复文件夹需要表级唯一性。
CREATE VIEW CheckUnique
WITH SCHEMABINDING
AS
SELECT fo.ParentFoldersID, fo.Name
FROM
Folders fo
JOIN
File fi ON fo.ParentFoldersID = fi.ParentFoldersID AND fo.Name = fi.Name
GO
CREATE UNIQUE CLUSTERED INDEX IXCU_CheckUnique ON CheckUnique (ParentFoldersID, Name)
GO
Run Code Online (Sandbox Code Playgroud)
或者触发器。
但绝不是检查约束中的 UDF
Rem*_*anu 13
CheckUniqueNameInFolder 函数几乎不检查任何东西。在该约束检查下可以添加大量重复项。它具有被顺序运行,并且,在任何情况下,约束讲述,充其量(因此的条件由所述第一选择可以由第二个运行时间被无效选中),有两个不同的SELECTS被没有重复检查时发生,绝不做它告诉大家,那里是当插入/更新不会出现重复。由于检查不会锁定在 U 或 X 模式下验证的键,因此可以同时进行多个插入,进行检查,发现没有重复项,然后全部继续插入相同的条目。
正确实施唯一约束的唯一方法是使用唯一约束。
使用“文件”的完整路径创建一个计算列,并使用 UNIQUE 约束在整个路径上强制执行唯一性,或者在 上使用 UNIQUE 约束(ParentFolderID, Name)。不要分别存储文件夹和文件,对文件夹和文件(例如条目)使用公共表,因为它们占用相同的命名空间。
在默认级别的事务中运行此命令read committed将在负载下失败。
读取不是互斥和序列化的,因此两个并发事务都可以读取该行不存在。您可以UPDLOCK,ROWLOCK,HOLDLOCK向SELECT.
| 归档时间: |
|
| 查看次数: |
2583 次 |
| 最近记录: |