Disclaimer

Данный блог является моей личной точкой зрения и не обязательно отражает точку зрения Oracle.

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle

Поиск

Подписка

Популярно о Supplemental Logging

05.02.2010 от aryndin99

Долго не доходили руки написать, но тема довольно важная в свете популярности репликации. Если достаточно просто понять для чего Supplemental Logging нужен, то вопросы об условном и обязательном журналировании, объеме дополнительно генерируемого потока журнальных данных и другие более тонкие технические вопросы всегда вызывают дополнительные вопросы.

Кроме того, еще и сам Oracle не так глубоко описывает это влияние, а если и описывает то в разных местах документации. Теоретическую информацию о Supplemental Logging еще можно найти в блогах и на металинке, но с практической информацией все сложно.

Для чего все это нужно? Я много пишу о репликации. Будь то Streams или GoldenGate - все они используют журналирование, чтобы получать изменения и транслировать их в целевую базу. А что произойдет, если база данных сильно нагружена? На какой объем дополнительной работы приходится рассчитывать? Все эти вопросы очень важны для обоснования выбора инструмента и для планирования наращивания оборудования...

Теория

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

В журналы пишутся так называемые журнальные записи (redo records). Каждая журнальная запись содержит все изменения для определенного SCN. Каждая журнальная запись состоит из заголовка и одного или нескольких векторов изменений (change vectors). Для каждого события может генерироваться несколько векторов изменений.

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

CHANGE #1 TYP:2 CLS:1 AFN:4 DBA:0x0100020e OBJ:74579 SCN:0x0000.000f8cbd SEQ:2 OP:11.2 ENC:0 RBL:0

Как можно видеть указаны Datablock Address, Object ID, SCN и номер версии блока (SEQ). Т.е. для того, чтобы воспроизвести операцию из Redo необходимо иметь блок с заданным адресом и заданной версией, иначе ничего не получится. Таким образом, если представить полную побайтную копию базы данных Oracle, то информации для наката изменений будет достаточно, но если объекты внутри базы смещены физически, то эта информация становится бесполезной.

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

Еще проблемы:

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

Итак, в журналы Oracle данные ложатся оптимальным образом для восстановления, а это не дает возможности использовать их для других целей. Для того, чтобы журналы позволили решать другие задачи нужен Supplemental Logging, о котором мы и будем говорить.

Что такое Supplemental Logging

Supplemental logging - это процесс записи дополнительной информации  в журнал во время выполнения операций изменения (например, изменения строки).

Supplemental log group - это набор столбцов, значения из которых должны быть журналированы, когда включено supplemental logging. Существует 2 типа групп: условные(conditional) и безусловные(unconditional):

  • Unconditional supplemental log groups - значение-до-изменения для столбцов, входящих в эту группу журналируются при любом изменении, независимо от того, изменяются  столбцы в этой группе. Часто такую группу столбцов называют ALWAYS log group.
  • Conditional supplemental log groups - значение-до-изменения для столбцов, входящих в эту группу журналируются только если изменяется хотя бы один из столбцов в этой группе.

Supplemental log groups могут быть созданы системой или определены пользователем.

Кроме того, что есть 2 типа групп существует также 2 уровня supplemental logging: database-level supplemental logging и table-level supplemental logging.

Database-level supplemental logging

Существует 2 типа database-level supplemental logging: minimal supplemental logging и identification key logging. Первый в отличие от второго не добавляет значительную нагрузку на базу данных. Oracle рекомендует как минимум включать minimal supplemental logging.

Minimal supplemental logging

В этом режиме база данных журналирует дополнительный объем данных, необходимый для идентификации, группировки и соединения операций Redo, связанных с DML изменениями. Включение такого журналирования позволяет продуктам, основанным на использовании журналов корректно обрабатывать chained rows, а также различные дополнительные методы хранения данных - cluster tables и IOT.

Включить:
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;

Выключить
ALTER DATABASE DROP SUPPLEMENTAL LOG DATA;

Я не буду вдаваться в подробности физической структуры Redo Log файлов. Если нужно, то можно посмотреть здесь и здесь. Кроме того, можно использовать команду ALTER SYSTEM DUMP LOGFILE для дампирования журнала.

Здесь же я просто приведу статистику по использованию файлов журнала в разных режимах. Для тестирования я создал 2 таблицы:

drop table test_without_chain;
create table test_without_chain (a1 number primary key,
a2 char(2000));

drop table  test_with_chain;
create table test_with_chain (a1 number primary key,
a2 char(2000),
a3 char(2000),
a4 char(2000),
a5 char(2000),
a6 char(2000));

Первая не должна приводить к row chain (у меня блок 8к), а вторая должна.

Таблица test_with_chain.

- Supp. Logging + Min Supp.
Logging
Прирост объема журналов
update test_with_chain
set a2=a2||'suffix';
2771748 2974612 7%
update test_with_chain set
a2=a2||'suffix', a3=a3||'suffix', a4=a4||'suffix',
a5=a5||'suffix', a6=a6||'suffix';
5671060 6051296 6%
10000 раз выполнен
insert into test_with_chain values
(i,'test1'||i, 'test2'||i, 'tes3'||i, 'test4'||i, 'test5'||i);
5810620 6014324 3%
delete from  test_with_chain; 5266460 5469020 4%

Таблица test_without_chain.

- Supp. Logging + Min Supp.
Logging
Прирост объема журналов
update test_without_chain
set a2=a2||'suffix';
4141300 4501832 8%
10000 раз выполнен
insert into test_without_chain values
(i,'test1'||i);
5217200 5423140 4%
delete from  test_without_chain; 4741424 4943292 4%

Из этих данных можно сделать, что основной прирост объема генерируемых данных мы испытываем на обновлениях таблиц - прирост около 7% объема журналов. На удалениях и вставках строк влияние в 2 раза меньше.

Database-Level Identification Key Logging

Используя database identification key logging можно включить журналирование состояния-до-изменения для всех таблиц в базе данных. В свою очередь database identification key logging имеет ряд режимов:

  • ALL - безусловно заставляет базу записывать в журналы состояние-до-изменения для всех столбцов в изменяемой строке (за исключением LOBs, LONGS, и ADTs).
  • PRIMARY KEY - безусловно (даже если первичный ключ не меняется) заставляет базу записывать в журналы состояние-до-изменения для первичного ключа в изменяемой строке. Если PK, то используется один из уникальных индексов. Если нет ни PK, ни уникального ключа, то Oracle ведет себя аналогично режиму ALL
  • UNIQUE - при условии, что изменяется столбец, входящий в уникальный или bitmap индекс, журналирует состояние-до-изменения для всех столбцов, принадлежащие этому индексу
  • FOREIGN KEY - при условии, что изменяет столбец, входящий в FK, журналирует состояние-до-изменения для всех столбцов FK.

При включении любого из этих режимов автоматически включается Minimal supplemental logging и его нельзя отключить, пока не будут отключены все режимы database identification key logging.

Включить:
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;

Выключить:
ALTER DATABASE DROP SUPPLEMENTAL LOG DATA (PRIMARY KEY) COLUMNS;

Давайте опять протестируем статистику генерации журналов в двух режимах - ALL и PRIMARY KEY. В скобках указан прирост в % к объему журналов без журналирования.

Без
Supp. Logging
+ Min Supp.
Logging
+PK +ALL
update test_with_chain
set a2=a2||'suffix';
2772004 2974612 (7%) 3175196 (13%) 3848308 (28%)
update test_with_chain set
a2=a2||'suffix', a3=a3||'suffix', a4=a4||'suffix',
a5=a5||'suffix', a6=a6||'suffix';
5671060 6051296 (6%) 6189932 (8%) 6189088 (8%)
10000 раз выполнен
insert into test_with_chain values
(i,'test1'||i, 'test2'||i, 'tes3'||i, 'test4'||i, 'test5'||i);
5810620 6014324 (3%) 6014744 (3%) 6014648 (3%)
delete from  test_with_chain; 5266460 5469020 (4%) 5469188 (4%) 5469436 (4%)

Как и следовало ожидать наибольший прирост объема журналирования произошел в случае изменения таблицы. Этот прирост становится значительным при обновлении только малого количества полей.

Очевидно, что связано это с тем, что поля, которые в данный момент не изменяются про на затрагиваются механизмом журналирования. Если же мы включаем журналирование состояния ВСЕХ столбцов до изменения, то неизменяемые столбцы также попадают в журнал.

Поэтому нужно быть очень аккуратным, когда включаете Supplemental Logging для всех операций. Нужно понимать, что это может привести к снижению производительности операций DML, но прежде всего, конечно, операций UPDATE.

Я бы вообще рекомендовал избегать использования глобального режима Supplemental Logging, а вместо него применять включение журналирования на уровне

Table-Level Identification Key Logging

Supplemental Logging на уровне таблиц позволяет включать те же самые режимы, что и на уровне базы данных ALL, PRIMARY KEY, UNIQUE, FOREIGN KEY. Например, что включить журналирование изменений состояния-до-изменения для всех столбцов таблицы:

ALTER TABLE HR.EMPLOYEES ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

Однако, помимо предопределенных режимов можно настроить режим, определенный пользователем. Так называемые Supplemental Log Groups.

Table-Level User-Defined Supplemental Log Groups

С помощью Supplemental Log Groups можно настроить списки столбцов, которые будут журналироваться. Различают 2 типа Supplemental Log Groups:

  • User-defined unconditional log groups - для создания безусловно журналируемых групп необходимо использовать ключевое слово ALWAYS. Для столбцов, входящих в такую группу, при каждом UPDATE в журнал записывается состояние-до-изменения. Значение столбца будет журналироваться даже если изменяются столбцы, не входящие в группу.
  • User-defined conditional supplemental log groups - для создания условно журналируемых групп необходимо опустить ключевое слово ALWAYS. Состояние-до-изменения для столбцов, входящих в такую группу будет записываться в журнал только если UPDATE изменяет столбцы в группе.

Пример создания user-defined unconditional log group:

ALTER TABLE HR.EMPLOYEES
ADD SUPPLEMENTAL LOG GROUP emp_parttime (EMPLOYEE_ID, LAST_NAME,
DEPARTMENT_ID) ALWAYS;

Пример создания user-defined conditional supplemental log group:

ALTER TABLE HR.EMPLOYEES
ADD SUPPLEMENTAL LOG GROUP emp_fulltime (EMPLOYEE_ID, LAST_NAME,
DEPARTMENT_ID);

Есть один нюанс, связанный с использованием User-defined log groups - количество столбцов не должно быть больше 32. Если столбцов больше нужно создавать несколько групп.

Представления для просмотра информации о Supplemental Logging

1. V$DATABASE - позволяет увидеть состояние Supplemental Logging на уровне базы данных:

select SUPPLEMENTAL_LOG_DATA_MIN,SUPPLEMENTAL_LOG_DATA_PK,SUPPLEMENTAL_LOG_DATA_UI,SUPPLEMENTAL_LOG_DATA_ALL from V$DATABASE;

2. ALL_LOG_GROUPS, ALL_LOG_GROUP_COLUMNS  - список Supplemental Log Groups и столбцов, входящих в них, для таблиц, к которомым пользователь имеет доступ:

select * from ALL_LOG_GROUPS a JOIN ALL_LOG_GROUP_COLUMNS b
on (a.owner=b.owner and a.log_group_name=b.log_group_name);

Заключение

Журналы Oracle предназначены в исходном состоянии для восстановления базы данных в аварийной ситуации. Их работа оптимальна и в них нет ничего лишнего.

Однако, для целей репликации данных там присутствует не все что нужно. Поэтому приходиться смиряться с этим неизбежным злом, поскольку в остальном репликация с использованием журналов Oracle очень эффективна. Все рассуждения в этой статье характерны как для Oracle Streams, так и для GoldenGate.

Хоть это и неизбежное зло, но мы можем значительно снизить дополнительную нагрузку за счет более грамотного тонкого включения Supplemental Logging. Включать его нужно на уровне таблиц и желательно продумывать, значения каких столбцов нужно дополнительно журналировать. Приведу пару примеров:

  • Обычно следует включать журналирование Primary Key
  • Если репликация двусторонняя, то нужно включать режим Supplemental Logging для столбцов, по которым возможно возникновение конфликта
  • Если в таблице Primary Key отсутствует по факту, но он формально поддерживается (например, в случае биллинга), то следует явно создать группу журналирования для столбца-первичного ключа.

Рубрики: Data Warehouse, Data Warehousing, Database, GoldenGate, Streams | Комментарии (3) »

Комментарии (3)

  1. Alex пишет:

    Получается что у «Supplemental Logging» только один недостаток он увеличивает Redo Logs, а что же по поводу нагрузки на апаратную часть системы? и на общую производительность базы. Насколько увеличивается нагрузка на базу ?

  2. aryndin99 пишет:

    Из-за увеличения объема журналов будет увеличена нагрузка на систему ввода-вывода.
    Возможно несколько вариантов:
    1. Журналы лежат на отдельно томе RAID 1, на котором другого I/O нет
    2. Журналы лежат на интеллектуальном хранилище, на RAID 10 с хорошим кэшем.
    3. Журналы лежат на том же диске, что и база. Объем кэша небольшой.

    В первых двух вариантах обычно эта нагрузка не приведет к заметным последствиям.
    В третьем варианте – будут проблемы. Ну третий вариант изначально будут работать плохо.

    Вот по процессорным ресурсам – нужно тестировать. Мое субъективное мнение – дополнительная нагрузка будет минимальной.

  3. comphead пишет:

    спс за статью.

Оставить комментарий

Заметьте: Включена проверка комментариев. Нет смысла повторно отправлять комментарий.