ORACLE MAGAZINE
Июль Поиск
Российское Электронное Издание

Общая методология
Новости и события
Опыт пользователей
Oracle Applications
Высокие технологии
Постоянная экспозиция
Мастерская разработчика
Кабинет администратора
Полезные ссылки
Архив







       КАБИНЕТ АДМИНИСТРАТОРА

Использование сегментов отката в Oracle 7.x - 8.x и проблема ORA-1555

1 июня 2000 г.

Б.Скворцов

Б.Скворцов

Введение

По данной теме сказано и написано немало. Достаточно вспомнить статью Ленг Тана “Наиболее важные аспекты управления транзакциями и сегментами отката” (“Oracle Magazine/Русское Издание” №1, 1997). В данной работе хотелось бы поделиться опытом по решению одной довольно часто встречающейся проблемы – это известная ошибка: ORA-01555: snapshot too old (rollback segment too small).

Общие положения

Известно, что при совместной работе нескольких транзакций, а именно в случаях одновременного выполнения запросов и изменения одних и тех же таблиц, для обеспечения согласованного чтения (consistent read) должны использоваться “старые” значения данных из строк читаемых таблиц, которые сохраняются в сегментах отката базы данных.

На рис.1 показано, как обеспечивается согласованность по чтению на уровне предложения с использованием данных в сегменте отката, исходя из значения SCN (system change number) - системного номера изменения, то есть последовательного номера состояния базы данных.

Рис.1

Когда запрос входит в фазу выполнения, выбирается текущий SCN (system change number). На рис.1 этот SCN равен 10023. При выборке данных в ходе запроса непосредственно читаются лишь те блоки данных, которые были записаны с меньшим, то есть более старым значением SCN. Блоки с изменившимися в ходе выполнения этого запроса данными, то есть блоки с большими значениями, новыми SCN, реконструируются с помощью данных, сохраненных в сегменте отката. Тем самым запрос возвращает пользователю “старые”, уже зафиксированные в базе на момент начала запроса реконструированные данные. Данные, как завершенных, так и незавершенных транзакций, изменившиеся за время выполнения запроса, не наблюдаются этим запросом, что гарантирует согласованность множества данных, видимых каждым запросом.

Каждый блок любого экстента сегмента отката может содержать информацию только об одной транзакции. Блоки, принадлежащие разным транзакциям, могут содержаться в одном экстенте. Логическая запись в сегменте отката включает в себя:

  • идентификатор транзакции;
  • идентификатор файла;
  • идентификатор блока;
  • номер строки;
  • номер колонки;
  • данные, которые были до изменения.

Обращение к блокам данных сегментов отката происходит через кэш буфера базы данных (buffer cache) SGA, эти блоки переписываются в журнальные файлы (redo log). Они могут понадобиться для процедур отката незавершенных транзакций (rollback) в случае восстановления экземпляра (instance recovery) после аварийного завершения, сбоя, в случае восстановления базы данных (media recovery).

Когда транзакция не находит свободных блоков внутри экстента сегмента отката, используется следующий по порядку экстент этого сегмента. Если текущий экстент является последним в сегменте, тогда данные записываются в первый экстент сегмента отката. Если первый экстент окажется целиком занятым (in use) данными отката незавершенных в настоящий момент транзакций, то выделяется новый экстент, и данные отката записываются в этот новый экстент.

Процесс выбора экстентов проиллюстрирован на рис.2. Допустим, Транзакция А уже использовала четыре экстента (3,4,5,6) для данных отката (рис.2, случай (а)) и ей ещё требуется место для данных отката. Так как транзакция уже использовала последний экстент сегмента, проверяется, не занят ли первый экстент сегмента отката активными данными (active data) отката других незавершенных транзакций. Если экстент свободен, то он будет использован как следующий - пятый экстент для Транзакции А (рис.2.b). Если же первый экстент используется другой незавершенной транзакцией (содержит активные данные), тогда сегмент отката расширяется. Новый экстент 7 будет использован как пятый экстент для Транзакции А (рис.2.с).

Рис.2.

ПРОБЛЕМА ORA-01555 : snapshot too old ( rollback segment to small )

В некоторых случаях, когда одновременно выполняются, и запросы, и изменения одних и тех же таблиц, согласованное множество данных (часто называемое снимком - snapshot) не может быть сформировано для долго выполняемого запроса. Этот феномен объясняется тем, что в сегментах отката оказывается недостаточно информации для того, чтобы реконструировать “старые” данные. Допустим, что Транзакция А завершилась. Использованные этой транзакцией блоки сегмента отката помечаются как неактивные (inactive). Данные Транзакции А не удаляются физически из сегмента отката, и могут быть использованы для создания согласованного (consistent) образа данных для Транзакции Б, которая начала выполняться до того, как произошло фиксирование данных Транзакции А. Проблема же заключается в том, что эти блоки могут быть перезаписаны другими транзакциями (в том числе и Транзакцией Б), даже в том случае, если "длинный" запрос еще не успел прочитать нужные “старые” блоки. У сервера Oracle нет информации о том, каким активным транзакциям (еще не завершившимся) могут понадобиться данные в уже неактивных блоках сегмента отката, и для более эффективного использования ресурсов вместо выделения очередного экстента используются освободившиеся (ставшие неактивными) блоки.

В ходе выполнения транзакции Oracle “сбрасывает” на диск модифицированные записи, помечая соответствующие блоки данных. Когда транзакция завершается, Oracle делает быстрый commit, отмечая транзакцию, как inactive, в таблице транзакций (TX table), которая находится в заголовке сегмента отката, но не снимает при этом отметки в блоках данных обычных таблиц. Следующая транзакция, который делает выборку из этих (dirty – грязный, модифицированный) блоков, фактически производит очистку (cleanout) блоков от пометок, сделанных предыдущей транзакцией. Это действие известно, как delayed block cleanout. Каждый блок Oracle содержит ITL - область, состоящая из слотов, в которых записаны сведения о транзакциях (каждый слот занимает 23 байта). Начальное количество слотов ITL определяется значением параметра INITRANS, а реальное - максимальным количеством транзакций, одновременно когда-либо обрабатывающих записи данного блока, но не меньше INITRANS и не больше MAXTRANS. Пусть, например, INITRANS равно 2, а час назад записи блока одновременно обновляли 5 транзакций. В этом случае требуется и выделяется 5 слотов, и после число слотов не уменьшается до 2. Слоты используются циклически.Таким образом, Oracle хранит сведения о пяти (в данном примере) транзакциях для этого блока. Обратим внимание, что это только ссылки на сегменты отката, а SCN, хранящиеся в TX-таблицах сегментов отката, могут быть уже затерты, как могут быть затерты и сами данные в сегментах.

Когда транзакция читает блок с нестертой(тыми) отметкой модификации, Oracle определяет, завершилась ли (по таблицам транзакций ТХ) транзакция, сделавшая эту отметку. Если да, то прочитанные данные зафиксированы (был выполнен commit), данными можно пользоваться, следует стереть отметку модификации. Если нет, то данными пользоваться нельзя, необходимо выбрать “старые” значения, сохраненные в сегменте отката. Если в этом случае запись о транзакции-модификаторе отсутствует в ТХ-таблице, то тогда и возникает ошибка ORA-1555.

[Прим. редактора: Механизм этого явления чуть-чуть тоньше и красивее. Поскольку каждый табличный блок данных заполнен в общем случае по разному, то для разных блоков одной и той же таблицы может быть построено разное число слотовITL. Из этого, по крайней мере, теоретически (практически это обнаружить, думаю, довольно сложно) следует, что на одной и тойже таблице в разные моменты времени одновременно может выполняться разное максимальное число транзакций. Далее. Поскольку единицей действия в базе данных Oracle является запись, то каждая запись в блоке связывается с одним из слотов ITL, хранит его номер, при помощи специального байта в заголовке каждой записи. Отсюда и следует ограничение значения параметра MAXTRANS – 255.]

[Прим. редактора(2): Не успели еще опубликовать эту статью, как по почте уже пришел вопрос, как раз описывающий ситуацию то с “зависанием”, то без “зависания” транзакций на одной и той же таблице, но на разных блоках. Механизм INITRANS сработал во всей красе. Внимание! Изменение значения параметра INITRANS начинает действовать только со следующего распределенного экстета, поэтому если обнаружились “зависания” транзакций по причине недостаточного значения параметра INITRANS, таблицу рекомендуется пересоздать.]

Рассмотрим две таблицы. Одна таблица была изменена, и транзакция по ней завершилась. По этой таблице открыт курсор, и затем в цикле начинает изменяться другая таблица. Казалось бы, здесь все корректно. Но, так как cleanout для первой таблицы не был сделан, для нее может возникнуть ORA-1555, так как блоки, необходимые для cleanout, в сегменте отката могли быть уже затерты транзакцией, модифицирующей вторую таблицу. Для предотвращения подобной проблемы Oracle рекомендует перед открытием курсора осуществлять полное сканирование таблицы, чтобы последующие чтения не осуществляли обращения к сегментам отката.

Существует несколько стандартных способов борьбы с данной сбойной ситуацией:

  • создание большего числа сегментов отката;
  • создание большого сегмента отката и выделение длинным транзакциям этих сегментов отката

( SET TRANSACTION USE ROLLBACK SEGMENT );

  • планирование по времени выполнения приложений - разделение приложений с длинными запросами (режим OLTP) и приложений, выполняющих массовые обновления данных (режим "batch processing").

Применение этих рекомендаций снижает вероятность появления ошибки "ORA-01555: Snapshot too old". Но эти методы решают проблему не полностью, так как в любой момент необходимые неактивные блоки сегмента отката могут быть перезаписаны. Единственный способ выйти из этой ситуации - это избежать перезаписи в сегменте отката определенного количества экстентов с неактивными блоками данными отката.

Один нестандартный способ был обнаружен в ходе эксплуатации некоего приложения, которое производило массовое обновление данных. Были перепробованы все варианты, но ситуация не становилась более стабильной. Грустное сообщение ORA-01555 время от времени появлялось снова. Был найден фрагмент в коде приложения, который потенциально мог быть причиной сбоя. Открытый курсор читал данные и передавал их в процедуру, которая и занималась собственно загрузкой. При этом после выхода из нее происходила модификация данных, которые попадали в область выборки курсора. Поиск подобных мест - достаточно трудная задача, а изменение логики работы, возможно, даже не разрешимая. Поэтому в качестве последнего варианта для работы этого приложения интуитивно было предложено создать сегмент отката с большим начальным размером, т.е. с большим минимальным количеством экстентов (параметр MINEXTENTS). Замечу, что параметр OPTIMAL, во избежание схлопывания этого сегмента отката, убрали уже давно. Подобная манипуляция сразу привела к положительному результату – загрузка завершилась успешно.

После анализа ситуации пришли к следующему выводам:

  • Oracle не использует неактивные блоки в экстентах сегмента отката до тех пор, пока есть свободные неиспользованные экстенты до размера MINEXTENTS;
  • работа транзакций в пределах MINEXTENTS сегмента отката может решить проблему перезаписи (для определенных объемов потребности транзакций), но чрезмерный расход дисковой памяти делает этот подход весьма неэффективным;
  • наиболее предпочтительным может быть решение, основанное на эффекте “блокирующей транзакции”.

Этот эффект базируется на том, что Транзакция В, которая началась раньше Транзакции А, имеет активные блоки в третьем экстенте (рис.3).

Рис.3

Когда Транзакция А займет все экстенты до MINEXTENTS, включается алгоритм поиска неактивных блоков, и транзакция займет экстент 1 и 2. Занять 5-й экстент транзакция не сможет, так как после 2-го экстента идет 3-й, занятый транзакцией В, который является активным. В результате будет выделен 6-й экстент за границей MINEXTENTS.

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

Известный специалист по технологиям Oracle Стив Адамс (Steve Adams), руководитель консалтинговой компании Ixora Pty Ltd (www.ixora.com.au), предложил красивое решение. Общая идея, излагаемая Адамсом, – это динамическое создание блокирующих транзакций для каждого сегмента отката. Транзакции модифицируют специальную таблицу и не делают commit в течение определенного времени, указанного при запуске. В течение этого времени в базе данных начинают работать все необходимые транзакции, требующие активного использования сегментов отката.

Технология блокирующих транзакций раскрывается в прилагаемых скриптах 1 - 4. После них приводятся еще три скрипта, близкие к рассматриваемой теме.

СПИСОК ЛИТЕРАТУРЫ

  1. “Oracle 8i Concepts”, Oracle corp., 1999
  2. “Oracle 8i Administrator’s Guide”, Oracle corp., 1999
  3. “Oracle 8i Application Developer’s Guide–Fundamentals”, Oracle corp.,1999
  4. “Oracle DBA Handbook” Kevin Loney, Oracle Press, 1994
  5. “Oracle Magazine (русское издание)”, 1(3)1997
  6. “Oracle8i Internal services for Waits, Latches, Locks and Memory” Steve Adams, O'Reily,1999.

Борис Скворцов,
отдел администрирования серверов баз данных,
Главный центр информатизации Банка России
sbg@gci.cbr.ru)

Скрипт 1. Создание вспомогательной таблицы в схеме SYSTEM

Скрипт 2. Создание shell-скрипта для запуска через вызов sqlplus скрипта protect_rbs.sql

Скрипт 3. Скрипт для создания блокирующей транзакции

Скрипт 4. Контроль состояния каждого сегмента отката.

Скрипт 5. Объем данных, записываемых транзакцией в сегмент отката

Скрипт 6. Память, выделяемая в сегменте отката

Скрипт 7. Мониторинг использования сегментов отката



Материал номера:
Новый тест для специалистов по Oracle


Колонка главного редактора:

Oracle открывает третье тысячелетие.

 Письмо в редакцию
 


Человек месяца: Беседа с руководителями ИВЦ АИС и WEB-центра “Омега”
Oracle: от МВД до РПЦ