Где хранится информация о блокировках? ITL, INITRANS, MAXTRANS

dbstalker, 13 мая

Что такое ITL и для чего он нужен?

В ORACLE, как вы наверняка знаете, нет менеджера блокировок. Об этом упоминалось и на моем блоге в посте Типы блокировок . Информация о блокировках хранится непосредственно в блоках данных. А если быть точным, то в заголовке блока, где заблокированная строка находится (см. здесь). Если другая транзакция желает заблокировать эту же запись, она должна добраться к блоку, содержащему запись, и по заголовку блока определить заблокирована ли необходимая строка. Где же именно в заголовке блока находится информация о блокировках? Для этого существует специальная структура, называемая таблицей списка входов транзакций ( ITL - Interested Transaction List ) или списком заинтересованных транзакций. В этой структуре хранится адрес транзакции и rowid заблокированной строки. ITL состоит из нескольких слотов.

Когда строка в блоке блокируется впервые, то транзакция устанавливает блокировку в одном из слотов с rowid блокируемой строки. Иначе говоря, транзакция ставит всех в известность, в своей «заинтересованности» этой строкой. Когда эта же или другая транзакция проявляет «заинтересованность» другой строкой, то информация помещается в следующий слот. И так далее. Когда транзакция завершается (commit, rollback), блокировки освобождаются, ITL –слоты также становятся свободными для других транзакций. Можно сказать, что таким образом на блочном уровне формируется очередь.

Какое количество слотов допустимо? Во время создания таблицы (CREATE TABLE) устанавливаются следующих два параметра: INITRANS и MAXTRANS.

INITRANS n

устанавливает начальное число транзакционных записей в каждом блоке. n должно быть целым числом в диапазоне от 1 до 255 (если опущено, то подразумевается n = 1, для 9 -ки - 2 и не меньше!). При первом использовании блока ORACLE резервирует в его свободной части 23 байта для каждой транзакции. Когда число одновременных транзакций превысит INITTRANS, новые транзакционные записи будут размещаться динамически до тех пор, пока их число не достигнет MAXTRANS или пока не заполнится блок.

MAXTRANS n

устанавливает максимальное число транзакций, имеющих возможность конкурентно модифицировать данные в блоке. n—целое, от 1 до 255. Подразумеваемое значение n = 255.

Можно сделать вывод, что при первоначальной записи данных в блок сразу же создается INITRANS слотов (по умолчанию 1).

В случае необходимости (одновременно несколько строк в блоке должны быть заблокированы) число слотов может возрасти до MAXTRANS или блок переполнится.

Если транзакция хочет установить блокировку на строку, а свободный слот отсутствует, то возникает ожидание «ITL waits».

Причины возникновения этого ожидания:

  • Низкое значение MAXTRANS
  • Переполнен блок
  • Обе эти причины

Чтобы уменьшить вероятность возникновения ITL waits , можно пойти следующим путями:

  • Увеличить MAXTRANS
  • Установить большим INITRANS, но не забывайте, что очень большое INITRANS может привести к неоправданной растрате пространства
  • Увеличить PCTFREE – меньше строк будет в блоке, значит меньше возможных блокировок, больше места для ITL.

Диагностика ITL ожидания ( рекомендации от http://www.dbazine.com/oracle/or-articles/nanda3)

Вот так можно обнаружить объекты, которые подвержены ITL ожиданию:

SELECT OWNER, OBJECT_NAME FROM V$SEGMENT_STATISTICS
WHERE STATISTIC_NAME = 'ITL waits' AND VALUE > 0

Если Вы подозреваете, что база данных зависла в ожидании, сделайте запрос:

select * from v$session_wait where event='enqueue'

И если нашлись такие сессии, то возможно это ITL waits. Для уточнения ситуации проанализируйте результаты выполнения следующего запроса:

Select s.sid  SID, s.serial#   Serial#, l.type type, ' '  object_name, lmode  held,  request  request
      from v$lock l, v$session s, v$process p
      where s.sid = l.sid and s.username <> ' ' and  s.paddr = p.addr and l.type <> 'TM' and (l.type <> 'TX' or l.type = 'TX' and l.lmode <> 6)
union
select  s.sid  SID,  s.serial# Serial#,  l.type  type,object_name object_name,lmode held,request request
      from v$lock l, v$session s, v$process p, sys.dba_objects o
      where s.sid = l.sid and o.object_id = l.id1 and  l.type = 'TM' and s.username <> ' ' and  s.paddr = p.addr
union
select s.sid  SID, s.serial#   Serial#,l.type type,'(Rollback='||rtrim(r.name)||')' object_name, lmode   held,request request
      from v$lock l, v$session s, v$process p, v$rollname r
      where s.sid = l.sid and l.type = 'TX' and l.lmode = 6 and trunc(l.id1/65536) = r.usn and s.username <> ' ' and s.paddr = p.addr
order by 5, 6

Информация и рисунки почерпнуты :

http://www.dbazine.com/oracle/or-articles/nanda3

 

Новый комментарий

Я не спамер: введите суму 1+6



 

От авторов блога

О Блоге - прочитай перед началом.

Задать вопрос и получить ответ - уже решено 94 вопросов

Глоссарий - список терминов и сокращений


 
 

Бизнес форум