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

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

ошибка в строке 1: ORA-00054: ресурс занят и приобретает с указанным NOWAIT или истекшим таймаутом

13 ответов


ваша таблица уже заблокирована некоторым запросом. Как вы выполнили "select for update"и еще не зафиксировали / откат и снова запустили запрос select. Выполните фиксацию / откат перед выполнением запроса.


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

вы также можете посмотреть sql, имя пользователя, машину, информацию о порте и перейти к фактическому процессу, который содержит соединение

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;

Пожалуйста, Убейте Сеанс Oracle

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

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


существует очень простая работа вокруг этой проблемы.

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

БЛОКИРОВКА ТАБЛИЦЫ 'TABLE_NAME' НЕТ ПОДОЖДИТЕ

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

специальные Примечание:

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

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

  1. заблокировать таблицу "имя таблицы"; -- вы будете "ждать" (разработчики называют это зависанием). до сеанса с открытой транзакцией, commits. Это очередь. так что впереди может быть несколько сеансов. но вы не ошибетесь.
  2. выполнить DDL. Затем ваш DDL запустит блокировку без ожидания. Тем не менее, ваш сеанс получил блокировку. Значит, ты хороший.
  3. ЯОД автоматической фиксации. Это освобождает замки.

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

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

Если вам интересно. Делаем это в 11g. Я сделал это в 10g раньше, а также в прошлом.


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

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

найти SID,

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

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

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

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

в производственной системе, это действительно зависит. Для oracle 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);

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


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

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


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

ниже 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';


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

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

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

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

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

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


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

  • удалите предложение внешнего ключа из инструкции CREATE TABLE
  • создайте индекс в столбце FK
  • создать FK

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

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

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

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


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


решение, данное ссылкой Шаши, является лучшим... нет необходимости связываться с dba или кем-то еще

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

create table xxxx_backup as select * from xxxx;

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

delete from xxxx;
commit;

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

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