ORA-00054: ресурс занят и приобретается с указанным NOWAIT или истечением времени ожидания

Почему я получаю эту ошибку базы данных при обновлении таблицы?

ОШИБКА в строке 1: ORA-00054: ресурс занят и приобретается с указанным NOWAIT или истечением времени ожидания.

Ответ 1

Ваша таблица уже заблокирована каким-либо запросом. Например, вы, возможно, выполнили команду "выбрать для обновления", но еще не зафиксировали/откатили и не запустили еще один запрос на выборку. Сделайте коммит/откат перед выполнением вашего запроса.

Ответ 2

отсюда ORA-00054: ресурс занят и приобретается с указанным NOWAIT

Вы также можете найти информацию о sql, username, machine, port и перейти к фактическому процессу, который содержит соединение

SELECT O.OBJECT_NAME, S.SID, S.SERIAL#, P.SPID, S.PROGRAM,S.USERNAME,
S.MACHINE,S.PORT , S.LOGON_TIME,SQ.SQL_FULLTEXT 
FROM V$LOCKED_OBJECT L, DBA_OBJECTS O, V$SESSION S, 
V$PROCESS P, V$SQL SQ 
WHERE L.OBJECT_ID = O.OBJECT_ID 
AND L.SESSION_ID = S.SID AND S.PADDR = P.ADDR 
AND S.SQL_ADDRESS = SQ.ADDRESS;

Ответ 3

Убейте сеанс Oracle Session

Используйте следующий запрос, чтобы проверить информацию активного сеанса

SELECT
    O.OBJECT_NAME,
    S.SID,
    S.SERIAL#,
    P.SPID,
    S.PROGRAM,
    SQ.SQL_FULLTEXT,
    S.LOGON_TIME
FROM
    V$LOCKED_OBJECT L,
    DBA_OBJECTS O,
    V$SESSION S,
    V$PROCESS P,
    V$SQL SQ
WHERE
    L.OBJECT_ID = O.OBJECT_ID
    AND L.SESSION_ID = S.SID
    AND S.PADDR = P.ADDR
    AND S.SQL_ADDRESS = SQ.ADDRESS;

убить как

alter system kill session 'SID,SERIAL#';

(Например, alter system kill session '13,36543';)

Ссылка http://abeytom.blogspot.com/2012/08/finding-and-fixing-ora-00054-resource.html

Ответ 4

Для этой проблемы очень легко работать.

Если вы запустите трассировку 10046 на своем сеансе (Google слишком... чтобы объяснить). Вы увидите, что перед любой DDL-операцией Oracle делает следующее:

LOCK TABLE 'TABLE_NAME' NO WAIT

Итак, если другой сеанс имеет открытую транзакцию, вы получаете сообщение об ошибке. Так что исправить... барабан рулон пожалуйста. Выпустите свой собственный замок перед DDL и оставьте "NO WAIT".

Специальное примечание:

Если вы выполняете разделение/удаление разделов, oracle просто блокирует раздел. - так что вы можете просто заблокировать подразделение.

Итак... Следующие шаги устраняют проблему.

  • LOCK TABLE 'TABLE NAME'; - вы будете "ждать" (разработчики называют это повешение). до завершения сеанса с открытой транзакцией. Это очередь. поэтому впереди вас может пройти несколько сеансов. но вы НЕ будете ошибаться.
  • Выполнить DDL. Затем ваш DDL запустит блокировку с NO WAIT. Однако ваша сессия приобрела замок. Итак, вы хорошо.
  • Автокоманды DDL. Это освобождает блокировки.

Операторы DML будут "ждать" или как разработчики называют это "зависанием", пока таблица заблокирована.

Я использую это в коде, который запускается из задания для удаления разделов. Он работает нормально. Он находится в базе данных, которая постоянно вставляется со скоростью в несколько сотен вставок в секунду. Нет ошибок.

если вам интересно. Делаю это в 11г. Я делал это в 10 г раньше, чем в прошлом.

Ответ 5

Эта ошибка возникает, когда ресурс занят. Проверьте, есть ли в запросе какие-либо ссылочные ограничения. Или даже таблицы, которые вы упомянули в запросе, могут быть заняты. Они могут быть связаны с другим заданием, которое будет определенно указано в следующих результатах запроса:

SELECT * FROM V$SESSION WHERE STATUS = 'ACTIVE'

Найти SID,

SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id

Ответ 6

Это происходит, когда сеанс, отличный от того, который использовался для изменения таблицы, удерживает блокировку, вероятно, из-за DML (update/delete/insert). Если вы разрабатываете новую систему, вполне вероятно, что вы или кто-то из вашей команды выдает сообщение об обновлении, и вы можете убить сеанс без особых последствий. Или вы можете совершить этот сеанс после того, как знаете, у кого открыт сеанс.

Если у вас есть доступ к системе администрирования SQL, используйте ее, чтобы найти оскорбительный сеанс. И, возможно, убить его.

Вы можете использовать v $session и v $lock и другие, но я предлагаю вам google, как найти этот сеанс, а затем как его убить.

В производственной системе это действительно зависит. Для оракула 10g и старше вы можете выполнить

LOCK TABLE mytable in exclusive mode;
alter table mytable modify mycolumn varchar2(5);

В отдельном сеансе, но в следующем случае он готов к завершению.

alter system kill session '....

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

В версии 11g есть новая переменная среды, которая устанавливает время ожидания. Я думаю, что это похоже на то, что я описал. Имейте в виду, что проблемы с блокировкой не исчезают.

ALTER SYSTEM SET ddl_lock_timeout=20;
alter table mytable modify mycolumn varchar2(5);

Наконец, лучше всего подождать, пока в системе не будет мало пользователей для такого обслуживания.

Ответ 7

В моем случае я был совершенно уверен, что это была одна из моих сессий, которая блокировала. Поэтому было безопасно сделать следующее:

  • Я нашел оскорбительную сессию с:

    SELECT * FROM V$SESSION WHERE OSUSER='my_local_username';

    Сеанс был неактивным, но все равно как-то удерживал блокировку. Обратите внимание, что вам может потребоваться использовать какое-то другое условие WHERE в вашем случае (например, попробуйте поля USERNAME или MACHINE).

  • Убил сессию, используя ID и SERIAL#, полученные выше:

    alter system kill session '<id>, <serial#>';

Отредактировано @thermz: Если ни один из предыдущих запросов открытого сеанса не работает, попробуйте этот. Этот запрос может помочь вам избежать синтаксических ошибок при отмене сеансов:

  • SELECT 'ALTER SYSTEM KILL SESSION '''||SID||','||SERIAL#||''' immediate;' FROM V$SESSION WHERE OSUSER='my_local_username_on_OS'

Ответ 8

Ваша проблема выглядит так, как будто вы смешиваете DML & DDL операции. Посмотрите этот URL, который объясняет эту проблему:

http://www.orafaq.com/forum/t/54714/2/

Ответ 9

Просто проверьте процесс проведения сессии и убейте его. Его обратно в норму.

Ниже SQL найдет ваш процесс

SELECT s.inst_id,
   s.sid,
   s.serial#,
   p.spid,
   s.username,
   s.program FROM   gv$session s
   JOIN gv$process p ON p.addr = s.paddr AND p.inst_id = s.inst_id;

Затем убейте его

ALTER SYSTEM KILL SESSION 'sid,serial#'

ИЛИ

Некоторый пример, который я нашел в Интернете, также нуждается в идентификаторе экземпляра alter system kill session '130,620, @1';

Ответ 10

Мне удалось ударить эту ошибку, просто создав таблицу! Там не было никаких проблем, очевидно, раздор на столе, который еще не существует. Оператор CREATE TABLE содержал предложение CONSTRAINT fk_name FOREIGN KEY, ссылающееся на хорошо заполненную таблицу. Мне пришлось:

  • Удалить предложение FOREIGN KEY из инструкции CREATE TABLE
  • Создайте INDEX в столбце FK
  • Создайте FK

Ответ 11

У меня была эта ошибка, когда у меня было 2 сценария, которые я запускал. У меня было:

  • Сессия SQL * Plus напрямую связана с учетной записью учетной записи схемы (учетная запись # 1)
  • Другой сеанс SQL * Plus, подключенный с использованием другой учетной записи пользователя схемы (учетная запись №2), но подключающийся по ссылке базы данных в качестве первой учетной записи

Я запустил таблицу, а затем создал таблицу как учетную запись # 1. Я провел обновление таблицы в сеансе # 2. Не совершал изменений. Повторно запустите таблицу drop/creation script как учетную запись # 1. Получена ошибка в команде drop table x.

Я решил это, запустив COMMIT; в сеансе SQL * Plus учетной записи №2.

Ответ 12

select
   c.owner,
   c.object_name,
   c.object_type,
   b.sid,
   b.serial#,
   b.status,
   b.osuser,
   b.machine
from
   v$locked_object a,
   v$session b,
   dba_objects c
where
   b.sid = a.session_id
and
   a.object_id = c.object_id;
   
   ALTER SYSTEM KILL SESSION 'sid,serial#';

Ответ 13

Удаление моего сообщения, поскольку оно не полезно в контексте вопроса. ORA-00054 происходит главным образом при выполнении DDL (ALTER, TRUNCATE и т.д.).

см. это

SELECT FOR UPDATE является единственным исключением как DML, я думаю.

Ответ 14

Я также сталкиваюсь с аналогичной проблемой. Для устранения этой ошибки ничего не требуется программисту. Я сообщил моей команде DBA оракула. Они убивают сеанс и работают как шарм.

Ответ 15

Решение, данное ссылкой Shashi, является лучшим... не нужно связываться с dba или кем-то еще

сделать резервную копию

create table xxxx_backup as select * from xxxx;

удалить все строки

delete from xxxx;
commit;

вставьте резервную копию.

insert into xxxx (select * from xxxx_backup);
commit;