Выполняются ли триггеры с текущим уровнем изоляции транзакции? - PullRequest
1 голос
/ 31 августа 2009

Рассмотрим таблицу с 3 столбцами: ID (уникальный, взятый из последовательности Oracle), CATEGORY и CODE (без ограничений для этих двух последних).

К каждой категории прикреплено несколько кодов, но коды должны быть уникальными в этой категории. Пример:

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

Третий не в порядке, так как у нас уже есть код Y для категории 1.

Теперь рассмотрим триггер, который запускается перед вставками и проверяет, в порядке ли значения для вставки. То есть для вставляемой записи триггер читает категорию, а затем считывает все коды из таблицы, которая имеет эту категорию, и если код из записи, которая должна быть вставлена, уже существует, то возникает исключение, так что запись не вставлено.

У меня вопрос: что триггер «увидит» в таблице, если уровень изоляции транзакции равен READ_COMMITED и две вставки выполняются в двух разных транзакциях практически в одно и то же время, но транзакция фиксируется позже?

Пример:

(1) Изначально таблица выглядит так:

ID    CATEGORY   CODE
1     1          X

(2) есть две транзакции T1 и T2 (уровень изоляции READ_COMMITED для обеих);

(3) обе транзакции хотят вставить категорию = 1 и код = 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

?!

Что триггеры "видят" и что происходит со вставкой?

1 Ответ

7 голосов
/ 31 августа 2009

Не используйте триггеры для такой проверки. Триггеры не масштабируются. Кроме того, как вы заметили, они не работают в многопользовательской среде. Вот почему Природа дала нам уникальные ограничения.

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