21 января 2009 г.

"buffer busy waits" и "read by other session"

В Oracle 10g появились ожидания read by other session, которые являются частным и "отколовшимся" случаем ожиданий buffer busy waits. Вот что пишут в документации Oracle о них:

This event ['read by other session'] occurs when a session requests a buffer that is currently being read into the buffer cache by another session. Prior to release 10.1, waits for this event ['read by other session'] were grouped with the other reasons for waiting for buffers under the 'buffer busy wait' event.
Наталья Гусева, одна из суперских ДБА, которых я знаю, подсказала, что read by other session - это тот же buffer busy waits с reason code = 130.
Reason code = 130: Block is being read by another session, and no other suitable block image was found, so we wait until the read is completed. This may also occur after a buffer cache assumed deadlock. The kernel can't get a buffer in a certain amount of time and assumes a deadlock. Therefore it will read the CR version of the block.
Полный список и описание reason code можно почитать здесь, правда там говорится применительно версии 9i.

Ожидания read by other session возникают, когда какая-то сессия пытается прочитать блок из диска в буферный кеш, в тот момент когда другая сессия уже читает ее из диска в буферный кеш.

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

В тестовых базах такие ожидания появлялись, когда кто-то забывал создать индексы после переноса схемы.

4 коммент.:

Алексей Шаляпин - это я. комментирует...

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

Oracle DBA комментирует...

Алексей, спасибо за комментарий:)

Анонимный комментирует...

Конкуренцию за блоки индексов (при большом числе индексов >10 на одной таблице) удалось снизить изменением текстов запросов, вызывающих подобную конкуренцию.
Тексты запросов были отловлены через анализ трассировки сессии. Включение/отключение трассировки:
start
sys.dbms_system.set_ev(sid, serial#, 10046, 12, '');
stop
sys.dbms_system.set_ev(sid, serial#, 10046, 0, '');
Выяснилось, что конкуренция за блок была связана с ожиданием освобождения "защелок".
Объекты (как позже оказалось в основном это были именно индексы) определились с помощью следующих запросов:
select hladdr, b.DBARFIL, b.DBABLK, sleeps, tch
from x$bh b, v$latch_children l
where l.NAME in ('cache buffers chains')
and l.ADDR=b.HLADDR
and sleeps>=10000
order by sleeps desc;
находим записи с наибольшими tch
и подставляем DBARFIL и DBABLK в следующий запрос
select * from dba_extents f where f.file_id= &DBARFIL
and &DBABLK between block_id and block_id+blocks-1;
в результате получаем список объектов.
Много сессий одновременно и читали и изменяли одни и те же блоки данных.
Метод конечно малость странноватый и муторный, но изменения запросов в конечном счете дали уменьшение количества ожиданий "защелок", да и разработчики освоили несколько новых команд :).
Oracle 9.2.0.8
Sun Solaris 5.8

Oracle DBA комментирует...

Спасибо большое, что поделились опытом!

Запросы, которые вы привели для определения блоков, при доступе к которым возникают эти ожидания:

select hladdr, b.DBARFIL, b.DBABLK, sleeps, tch
from x$bh b, v$latch_children l
where l.NAME in ('cache buffers chains')
and l.ADDR=b.HLADDR
and sleeps>=10000
order by sleeps desc;

и запрос выдающий название объектов по номеру файла и блока:
select * from dba_extents f where f.file_id= &DBARFIL
and &DBABLK between block_id and block_id+blocks-1;

- очень полезны для выяснения причин таких ожиданий.
Удачи в работе!