Возможно ли возникновение взаимоблокировки, если два одновременных оператора DML изменяют одни и те же данные и используют один и тот же метод доступа?
Исходя из моих тестов и моих предположений о том, как работает Oracle, ответ - нет.
Но я хочу быть на 100% уверенным. Я ищу официальный источник, который говорит, что взаимоблокировки не могут происходить таким образом, или тестовый пример, демонстрирующий, что взаимоблокировки могут возникать таким образом.
Другой способ задать этот вопрос: будет ли Oracle всегда возвращать результаты в том же порядке, если используется один и тот же метод доступа? (И никаких изменений данных между прогонами.)
Например, если запрос использует полное сканирование таблицы и возвращает строки в порядке 4/3/2/1, будет ли всегда возвращать строки в этом порядке? И если сканирование диапазона индекса возвращает строки в порядке 1/2/3/4, будет ли всегда возвращать строки в этом порядке? Неважно, каков фактический порядок, просто он является детерминированным.
(Параллелизм может добавить некоторую сложность этому вопросу. Общий порядок выражения будет различным в зависимости от многих факторов. Но для блокировки я считаю, что важен только порядок в каждом параллельном сеансе. И снова мое тестирование показывает, что порядок является детерминированным и не приведет к тупику.)
UPDATE
Мой оригинальный вопрос был немного общим. Больше всего меня интересует, можно ли запустить что-то вроде update table_without_index set a = -1
в двух разных сеансах одновременно и получить взаимоблокировку? (Я спрашиваю об одном обновлении, а не о серии обновлений.)
Во-первых, позвольте мне продемонстрировать, что одно и то же утверждение может вызвать тупик.
Создать таблицу, индекс и некоторые данные:
Для простоты я обновляю только тот же столбец. В реальном мире были бы разные столбцы, но я не думаю, что это что-то меняет.
Обратите внимание, что я создаю таблицу с pctfree 0, и обновленные значения будут занимать значительно больше места, поэтому будет много миграций строк. (Это ответ на ответ @Tony Andrew, хотя я боюсь, что мой тест может быть слишком упрощенным. Кроме того, я не думаю, что нам нужно беспокоиться о вставке строк между обновлениями; только одно из обновлений увидит новую строку, поэтому это не приведет к тупику. Если новый ряд не переместит также кучу других вещей.)
drop table deadlock_test purge;
create table deadlock_test(a number) pctfree 0;
create index deadlock_test_index on deadlock_test(a);
insert into deadlock_test select 2 from dual connect by level <= 10000;
insert into deadlock_test select 1 from dual connect by level <= 10000;
commit;
Запустить этот блок в сеансе 1:
begin
while true loop
update deadlock_test set a = -99999999999999999999 where a > 0;
rollback;
end loop;
end;
/
Запустить этот блок в сеансе 2:
--First, influence the optimizer so it will choose an index range scan.
--This is not gaurenteed to work for every environment. You may need to
--change other settings for Oracle to choose the index over the table scan.
alter session set optimizer_index_cost_adj = 1;
begin
while true loop
update deadlock_test set a = -99999999999999999999 where a > 0;
rollback;
end loop;
end;
/
Через несколько секунд одна из этих сессий выдает ORA-00060: deadlock detected while waiting for resource
. Это связано с тем, что один и тот же запрос блокирует строки в разном порядке в каждом сеансе.
За исключением описанного выше сценария, может ли произойти тупик?
Выше показано, что изменение плана выполнения может привести к тупику.
Но может ли возникнуть тупик, даже если план выполнения останется прежним?
Насколько я могу судить, если вы удалите optimizer_index_cost_adj
или что-либо еще, что изменит план, код никогда не вызовет тупиковую ситуацию. (Я выполняю код некоторое время без ошибок.)
Я задаю этот вопрос, потому что система, над которой я работаю, иногда случается. Это еще не удалось, но мы хотим знать, действительно ли это безопасно, или нам нужно добавить дополнительную блокировку вокруг обновлений?
Может ли кто-нибудь создать тестовый сценарий, в котором один оператор обновления, выполняющийся одновременно и использующий один и тот же план, вызывает тупик?