2015-04-15 3 views
2

Мы столкнулись с проблемами в нашей базе данных оракула 11g, касающейся блокировки таблиц.Может ли таблица быть заблокирована другой таблицей?

У нас есть процедура, которая выполняется через sql * plus, которая обрезает таблицу, скажем, table1. Иногда мы получаем ORA-00054: ресурс занят и приобретаем с ошибкой NOWAIT во время выполнения процедуры в той части, где таблица должна быть усечена. У нас есть webapp, который находится на сервере tomcat, который при перезапуске (чтобы убить сеансы в базе данных от tomcat), процедура может быть успешно выполнена. table1 не используется, даже не в select, в исходном коде для webapp, но много родительской таблицы таблицы1.

Возможно ли, что незафиксированное обновление одной из его родительской таблицы вызывает блокировку ?. Если да, то какие-либо предложения о том, как я могу это проверить? Я проверил с администратором базы данных в те моменты, когда мы столкнулись с проблемой, но он не может получить сеанс, который блокирует процедуру и инструкцию, вызвавшую блокировку.

+0

См: http://stackoverflow.com/questions/4842765/ora-00054-resource-busy-and-acquire-with-nowait-specified-or-timeout-expired – Syntax

ответ

1

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

Поиск и отслеживание конкретной проблемы с прерывистой блокировкой может быть болезненным. Даже если вы не можете отслеживать конкретные условия, было бы неплохо изменить любой код, чтобы избежать одновременных DML и DDL. Это может не только вызвать проблемы с блокировкой, но также может сломать операторы SELECT.

При удалении параллелизм может быть и речи, вы можете по крайней мере, необходимо включить DDL_LOCK_TIMEOUT так что truncate заявление будет ждать замок вместо немедленно неудачу: alter session set ddl_lock_timeout = 100000;

--Create parent/child tables, with or without an indexed foreign key. 
create table parent_table(a number primary key); 
insert into parent_table values(1); 
insert into parent_table values(2); 
create table child_table(a number references parent_table(a)); 
insert into child_table values(1); 
commit; 

--Session 1: Update parent table. 
begin 
    loop 
     update parent_table set a = 2 where a = 2; 
     commit; 
    end loop; 
end; 
/

--Session 2: Truncate child table. Eventulaly it will throw this error: 
--ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired 
begin 
    loop 
     execute immediate 'truncate table child_table'; 
    end loop; 
end; 
/
0

любые предложения о том, как я могу проверить это?

Вы можете проверить блокировки сеансов, когда вы получите ORA-00054: resource busy and acquire with NOWAIT ошибку.

Блокирующие сеансы происходят, когда в одном сеансе выполняется эксклюзивная блокировка на объекте и не выпускается, пока другие сеансы не захотят обновлять одни и те же данные. Это будет блокировать второй, пока первый не сделает COMMIT или ROLLBACK.

SELECT 
    s.blocking_session, 
    s.sid, 
    s.serial#, 
    s.seconds_in_wait 
FROM 
    v$session s 
WHERE 
    blocking_session IS NOT NULL; 

Например, см мой аналогичный ответ here и here.

Смежные вопросы