2010-02-02 2 views
10

У нас есть база данных Oracle, а таблица учетных записей имеет около миллиона строк. На протяжении многих лет мы создали четыре разных пользовательских интерфейса (два в Oracle Forms, два в .Net), все из которых остаются в использовании. У нас есть ряд фоновых задач (как постоянных, так и запланированных).Как найти заблокированные строки в Oracle

Что-то иногда держит длинный замок (скажем, более 30 секунд) в строке в таблице учетных записей, что приводит к сбою одной из постоянных фоновых задач. Запрашиваемая фоновая задача перезапустится после истечения времени обновления. Мы узнаем об этом через несколько минут после этого, но к тому времени блокировка была выпущена.

У нас есть основания полагать, что это может быть неправильный пользовательский интерфейс, но он не смог найти «курящее оружие».

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

Мы находимся на 11 г, но испытываем проблему с 8i.

ответ

10

Oracle Концепция блокировки шлюза сильно отличается от концепции других систем.

Когда строка в Oracle заблокирована, сама запись обновляется с новым значением (если есть) и, кроме того, помещается блокировка (которая по существу является указателем на блокировку транзакций, которая находится в сегменте отката) прямо в запись.

Это означает, что запись записи в Oracle означает обновление метаданных записи и выдачу логической записи страницы. Например, вы не можете сделать SELECT FOR UPDATE в табличном пространстве только для чтения.

Более того, сами записи не обновляются после фиксации: вместо этого сегмент отката обновляется.

Это означает, что каждая запись содержит некоторую информацию о транзакции, которая в последний раз ее обновляла, даже если сама транзакция уже давно умерла. Чтобы узнать, жива или нет транзакция (и, следовательно, если запись живая или нет), необходимо посетить сегмент отката.

В Oracle нет традиционного менеджера блокировок, а это значит, что для получения списка всех блокировок требуется сканирование всех записей во всех объектах. Это займет слишком много времени.

Вы можете получить специальные блокировки, такие как заблокированные объекты метаданных (с использованием v$locked_object), блокировка ожидания (с использованием v$session) и т. Д., Но не список всех блокировок для всех объектов в базе данных.

+0

Cant»вы используете V $ ЗАМОК, чтобы получить все замки? Даже если вы не можете определить конкретные строки, которые блокируются, по крайней мере вы знаете, какие таблицы. –

4

Вместо блокировок, я предлагаю вам посмотреть долгосрочные сделки, используя v$transaction. Оттуда вы можете присоединиться к v$session, что должно дать вам представление об пользовательском интерфейсе (попробуйте колонки программы и машины), а также пользователя.

4

Посмотрите на dba_blockers, dba_waiters и dba_locks для блокировки. Имена должны быть само собой разумеющимися.

Вы можете создать задание, которое выполняется, скажем, один раз в минуту, и регистрирует значения в dba_blockers и текущий активный sql_id для этого сеанса. (через v $ session и v $ sqlstats).

Вы также можете посмотреть в v $ sql_monitor.Это будет по умолчанию регистрировать весь SQL, который занимает больше 5 секунд. Он также отображается на странице «Мониторинг SQL» в Enterprise Manager.

+0

'dba_blockers' и другие мнения, о которых вы упомянули, будут перечислять только блокировки, ожидающие. @op уточнил, что он хочет, чтобы все блокировки, а не только те, на которых были зарегистрированы. – Quassnoi

+0

Но если ничто не блокируется, сеанс может блокироваться до тех пор, пока он нравится, так как это не повлияет на производительность. Только блокирующие блоки влияют на производительность. – PenFold

1

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

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; 
Смежные вопросы