考虑一个包含3列的表:ID(唯一,取自Oracle序列),CATEGORY和CODE(最后两个没有约束)。
每个类别都附加了多个代码,但代码在该类别中必须是唯一的。例如:
ID CATEGORY CODE
1 1 X
2 1 Y
3 1 Y //wrong
第三个不正常,因为我们已经为类别1提供了代码Y.
现在考虑在插入和检查之前运行的触发器,以查看要插入的值是否正常。也就是说,对于正在插入的记录,触发器读取类别,然后从表中读取具有该类别的所有代码,如果必须插入的记录中的代码已经存在,则引发异常以便记录未插入。
我的问题是,如果事务隔离级别是READ_COMMITED
,那么触发器会在表中“看到”,并且在几乎完全相同的时间在两个不同的事务中执行了两个插入但事务稍后提交了?
示例:
(1)最初,表格如下:
ID CATEGORY CODE
1 1 X
(2)有两个事务T1和T2(两者的隔离级别READ_COMMITED
);
(3)两个交易都要插入category = 1和code = Y;
(4)T1执行插入并执行触发器。表格中没有Y,因此可以插入;
(5)T2执行插入并执行触发器。表中没有Y(T1尚未提交),因此可以插入;
(6)T1提交,表现在看起来像这样:
ID CATEGORY CODE
1 1 X
2 1 Y
(7)T2现在提交。这里发生了什么?我是否收到错误且没有插入记录,或者我得到下表:
ID CATEGORY CODE
1 1 X
2 1 Y
3 1 Y //this is wrong
?!
触发器“看到”什么以及插入会发生什么?
答案 0 :(得分:7)
请勿使用触发器进行此类验证。触发器不会缩放。此外,您已经注意到它们无法在多用户环境中工作。这就是大自然赋予我们独特限制的原因。
alter table your_table
add constraint yr_tab_uk unique (category, code)
using index
/