Почему я получаю эту ошибку базы данных при обновлении таблицы?
ОШИБКА в строке 1: ORA-00054: ресурс занят и приобретается с указанным NOWAIT или истечением времени ожидания.
Почему я получаю эту ошибку базы данных при обновлении таблицы?
ОШИБКА в строке 1: ORA-00054: ресурс занят и приобретается с указанным NOWAIT или истечением времени ожидания.
Ваша таблица уже заблокирована каким-либо запросом. Например, вы, возможно, выполнили команду "выбрать для обновления", но еще не зафиксировали/откатили и не запустили еще один запрос на выборку. Сделайте коммит/откат перед выполнением вашего запроса.
отсюда 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;
Убейте сеанс 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
Для этой проблемы очень легко работать.
Если вы запустите трассировку 10046 на своем сеансе (Google слишком... чтобы объяснить). Вы увидите, что перед любой DDL-операцией Oracle делает следующее:
LOCK TABLE 'TABLE_NAME' NO WAIT
Итак, если другой сеанс имеет открытую транзакцию, вы получаете сообщение об ошибке. Так что исправить... барабан рулон пожалуйста. Выпустите свой собственный замок перед DDL и оставьте "NO WAIT".
Специальное примечание:
Если вы выполняете разделение/удаление разделов, oracle просто блокирует раздел. - так что вы можете просто заблокировать подразделение.
Итак... Следующие шаги устраняют проблему.
Операторы DML будут "ждать" или как разработчики называют это "зависанием", пока таблица заблокирована.
Я использую это в коде, который запускается из задания для удаления разделов. Он работает нормально. Он находится в базе данных, которая постоянно вставляется со скоростью в несколько сотен вставок в секунду. Нет ошибок.
если вам интересно. Делаю это в 11г. Я делал это в 10 г раньше, чем в прошлом.
Эта ошибка возникает, когда ресурс занят. Проверьте, есть ли в запросе какие-либо ссылочные ограничения. Или даже таблицы, которые вы упомянули в запросе, могут быть заняты. Они могут быть связаны с другим заданием, которое будет определенно указано в следующих результатах запроса:
SELECT * FROM V$SESSION WHERE STATUS = 'ACTIVE'
Найти SID,
SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id
Это происходит, когда сеанс, отличный от того, который использовался для изменения таблицы, удерживает блокировку, вероятно, из-за 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);
Наконец, лучше всего подождать, пока в системе не будет мало пользователей для такого обслуживания.
В моем случае я был совершенно уверен, что это была одна из моих сессий, которая блокировала. Поэтому было безопасно сделать следующее:
Я нашел оскорбительную сессию с:
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'
Ваша проблема выглядит так, как будто вы смешиваете DML & DDL операции. Посмотрите этот URL, который объясняет эту проблему:
Просто проверьте процесс проведения сессии и убейте его. Его обратно в норму.
Ниже 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';
Мне удалось ударить эту ошибку, просто создав таблицу! Там не было никаких проблем, очевидно, раздор на столе, который еще не существует. Оператор CREATE TABLE
содержал предложение CONSTRAINT fk_name FOREIGN KEY
, ссылающееся на хорошо заполненную таблицу. Мне пришлось:
У меня была эта ошибка, когда у меня было 2 сценария, которые я запускал. У меня было:
Я запустил таблицу, а затем создал таблицу как учетную запись # 1.
Я провел обновление таблицы в сеансе # 2. Не совершал изменений.
Повторно запустите таблицу drop/creation script как учетную запись # 1. Получена ошибка в команде drop table x
.
Я решил это, запустив COMMIT;
в сеансе SQL * Plus учетной записи №2.
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#';
Удаление моего сообщения, поскольку оно не полезно в контексте вопроса. ORA-00054
происходит главным образом при выполнении DDL (ALTER, TRUNCATE и т.д.).
SELECT FOR UPDATE
является единственным исключением как DML, я думаю.
Я также сталкиваюсь с аналогичной проблемой. Для устранения этой ошибки ничего не требуется программисту. Я сообщил моей команде DBA оракула. Они убивают сеанс и работают как шарм.
Решение, данное ссылкой Shashi, является лучшим... не нужно связываться с dba или кем-то еще
сделать резервную копию
create table xxxx_backup as select * from xxxx;
удалить все строки
delete from xxxx;
commit;
вставьте резервную копию.
insert into xxxx (select * from xxxx_backup);
commit;