简体   繁体   English

触发器是否以当前事务隔离级别执行?

[英]Are triggers executed with the current transaction isolation level?

Consider a table with 3 columns: ID (unique, taken from an Oracle sequence), CATEGORY and CODE (no constraints on these last two). 考虑一个具有3列的表:ID(唯一性,取自Oracle序列),CATEGORY和CODE(对后两个无约束)。

Each category has multiple codes attached to it, but the codes must be unique within that category. 每个类别都有多个附加的代码,但是这些代码在该类别内必须唯一。 Example: 例:

ID    CATEGORY   CODE
1     1          X
2     1          Y
3     1          Y     //wrong

The third one is not OK since we already have code Y for the category 1. 第三个不正确,因为我们已经有类别1的代码Y。

Now consider a trigger that runs before inserts and checks to see if the values to be inserted are OK. 现在考虑在插入之前运行的触发器,并检查要插入的值是否正确。 That is, for the record that is being inserted the trigger reads the category, and then reads all codes from the table that have that category, and if the code from the record that must be inserted already exists then raises an exception so that the record is not inserted. 也就是说,对于要插入的记录,触发器将读取该类别,然后从具有该类别的表中读取所有代码,如果必须插入的记录中的代码已经存在,则会引发异常,以便该记录未插入。

My question is what will the trigger "see" in the table if the transaction isolation level is READ_COMMITED and there are two inserts executed in two different transactions at almost exactly the same time but the transaction is committed later? 我的问题是,如果事务隔离级别为READ_COMMITED并且几乎在同一时间在两个不同的事务中执行了两个插入操作,但稍后又提交了该事务,则触发器将在表中看到什么?

Example: 例:

(1) Initially, the table looks like this: (1)最初,该表如下所示:

ID    CATEGORY   CODE
1     1          X

(2) there are two transactions T1 and T2 (isolation level READ_COMMITED for both); (2)有两个事务T1和T2(两者的隔离级别READ_COMMITED );

(3) both transactions want to insert category = 1 and code = Y; (3)两个交易都想插入类别= 1和代码= Y;

(4) T1 performs the insert and the trigger is executed. (4)T1执行插入操作并执行触发器。 There is no Y in the table so it is OK to insert; 表中没有Y,因此可以插入;

(5) T2 performs the insert and the trigger is executed. (5)T2执行插入操作并执行触发器。 There is no Y in the table (T1 has not yet commited) so it is OK to insert; 表中没有Y(尚未提交T1),因此可以插入;

(6) T1 commits and the table now looks like this: (6)T1提交,该表现在如下所示:

ID    CATEGORY   CODE
1     1          X
2     1          Y

(7) T2 now commits. (7)现在提交T2。 What happens here? 这里会发生什么? Do I get an error and the record is not inserted or I get the following table: 我收到错误消息并且未插入记录吗?还是得到下表:

ID    CATEGORY   CODE
1     1          X
2     1          Y
3     1          Y     //this is wrong

?! ?!

What do the triggers "see" and what happens to the insert? 触发器“看到”了什么,插入发生了什么?

Don't use triggers for such validation. 不要使用触发器进行此类验证。 Triggers don't scale. 触发器不缩放。 Also, as you have noticed they don't work in multi-user environments. 另外,您已经注意到它们在多用户环境中不起作用。 This is why Nature gave us unique constraints. 这就是自然给我们独特约束的原因。

alter table your_table
    add constraint yr_tab_uk unique (category, code)
    using index
/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM