УПРАВЛЕНИЕ СНИМКАМИ
Эта глава описывает, как использовать снимки таблиц для
поддержания копий таблиц на удаленных узлах, что позволяет
избегать удаленных запросов. Темы этой главы включают
обсуждение следующих вопросов:
* механизмы средства снимков таблиц
* рекомендации по использованию снимков
* альтернативы снимкам таблиц
Информация этой главы применима лишь к системам, использующим
ORACLE с распределенной опцией.
Обратитесь к документу Trusted ORACLE7 Server Administrator's
Guide для информации о дополнительных требованиях по управлению
снимками в среде Trusted ORACLE.
----------------
Когда использовать снимки
Средство снимков таблицы применимо при следующих условиях:
* Главная таблица редко обновляется, но часто опрашивается.
* Пользователи опрашивают данные главной таблицы из разных
узлов в системе распределенной базы данных.
Принимая решение о том, создавать ли снимки по данной таблице,
вы должны принимать во внимание также и стоимость. Каждая база
данных, вовлекаемая в связь главная таблица/снимок, принимает на
себя дополнительные накладные расходы, - как по обработке (для
обновления каждого снимка), так и по памяти (для хранения
каждого снимка). Неоправданное использование снимков без
необходимости снижает производительность базы данных и
увеличивает расходы дисковой памяти.
----------------
Создание снимков
Вы создаете локальный снимок с помощью команды SQL CREATE
SNAPSHOT. Как и при создании таблицы, вы можете специфицировать
характеристики памяти для блоков данных снимка, размеры и
распределение эсктентов, а также табличное пространство, в
котором создается снимок; альтернативно, вы можете
специфицировать кластер, в котором будет создан снимок. Как
уникальную особенность снимков, вы можете также указать, как
должен освежаться снимок, и задать распределенный запрос,
который определяет этот снимок. Например, следующее предложение
CREATE SNAPSHOT определяет локальный снимок для дублирования
таблицы EMP, расположенной в базе данных NY:
CREATE SNAPSHOT emp_sf
PCTFREE 5 PCTUSED 60
TABLESPACE USERS
STORAGE (INITIAL 50K NEXT 50K PCTINCREASE 50)
REFRESH FAST
START WITH sysdate
NEXT sysdate + 7
AS SELECT * FROM emp@ny;
Когда снимок создается, он немедленно заполняется строками,
возвращаемыми запросом, который определяет этот снимок.
Впоследствии снимок периодически освежается, как специфицировано
фразой REFRESH; для информации об освежении снимков обратитесь к
документу ORACLE7 Server Administrator's Guide.
Именование снимков
------------------
Снимки содержатся в схеме пользователя. Имя снимка должно быть
уникальным по отношению к другим объектам в этой схеме (таким
как таблицы и обзоры).
Спецификация определяющего запроса снимка
-----------------------------------------
Определяющий запрос снимка может быть любым действительным
запросом по таблицам, обзорам или другим снимкам, не
принадлежащим пользователю SYS. Этот запрос не может содержать
фраз ORDER BY или FOR UPDATE. Кроме того, простые снимки
определяются через обзоры, которые не могут содержать фраз GROUP
BY или CONNECT BY, соединений, подзапросов и операторов
множеств.
Запрос, определяющий снимок, может создавать структуру, отличную
от структуры главной таблицы. Например, следующее предложение
CREATE SNAPSHOT создает локальный снимок с именем EMP_DALLAS (по
главной таблице, расположенной в Нью-Йорке), который содержит
лишь столбцы EMPNO, ENAME и MGR главной таблицы, и лишь те
строки, которые содержат сотрудников отдела 10:
CREATE SNAPSHOT emp_dallas
.
.
.
AS SELECT empno, ename, mgr
FROM emp@ny
WHERE deptno = 10;
Создание кластеризованного снимка
---------------------------------
Вы можете создать снимок в кластере, точно так же, как и
таблицу. Например, следующее предложение создает снимок с
именем EMP_DALLAS в кластере EMP_DEPT:
CREATE SNAPSHOT emp_dallas
.
.
.
CLUSTER emp_dept
.
.;
Для кластеризованного снимка используются параметры памяти
сегмента данных кластера, даже если при создании такого снимка
специфицированы параметры памяти.
Привилегии, требуемые для создания снимков
------------------------------------------
Для создания снимков необходимы следующие группы привилегий:
* Чтобы создать снимок в своей схеме, вы должны иметь
системные привилегии CREATE SNAPSHOT, CREATE TABLE,
CREATE VIEW и CREATE INDEX (только для простых снимков),
а также привилегию SELECT по главным таблицам.
* Чтобы создать снимок в схеме другого пользователя, вы
должны иметь системные привилегии CREATE ANY SNAPSHOT,
CREATE ANY TABLE, CREATE ANY VIEW и CREATE ANY INDEX
(только для простых снимков), а также привилегию SELECT
по главным таблицам. Кроме того, владелец снимка должен
иметь соответствующие привилегии SELECT по главным
таблицам.
В любом случае, владелец снимка должен также иметь достаточную
квоту на табличное пространство, в котором создается снимок.
Столь большой набор привилегий, требуемый для создания снимка,
объясняется объектами, которые также должны быть созданы от
имени этого снимка.
Сложные снимки против локальных обзоров
---------------------------------------
Принимая решение о создании сложного снимка, рассмотрите
альтернативный вариант: создать простые снимки и выполнять
сложный запрос, используя обзор по удаленной базе данных.
Рис.12-1 иллюстрирует преимущества и недостатки обоих этих
методов.
Рис.12-1
Два метода реализации сложных снимков
БАЗА ДАННЫХ I ¦ БАЗА ДАННЫХ II
¦
Таблица EMP ¦
--------¬ ¦
¦ ¦ ¦ Снимок EMP_DEPT
¦ ¦ Полное ¦ ---------------------------------¬
L-------- освежение ¦ ¦ SELECT ... ¦
A ¦=============+== ¦ FROM emp@ny, dept@ny ¦
ТаблицаDEPT ¦ ¦ WHERE emp.deptno = dept.deptno ¦
-----¬ ¦ L---------------------------------
¦ ¦ ¦
¦ ¦ ¦ ‑ Высокая производитель-
L----- ¦ ¦ ность запроса
¦ ¦
¦ SELECT ... FROM emp_dept;
¦ ¦
¦ ¦
¦ Приемлемая производи-
¦ тельность запроса
¦
Таблица EMP Журнал EMP ¦ Снимок EMP
--------¬ -------¬ ¦ --------¬
¦ ¦ ¦ ¦ ---+---¦ ¦
¦ ¦ L------- ¦ ¦ ¦ Обзор EMP_DEPT
L-------- ¦ L-------- ---------------------¬
B ¦ ¦ SELECT ... ¦
Таблица DEPT Журнал DEPT¦ Снимок DEPT ¦ FROM emp, dept ¦
-----¬ ----¬ ¦ -----¬ ¦ WHERE emp.deptno = ¦
¦ ¦ ¦ ¦ ------+---¦ ¦ ¦ dept.deptno ¦
¦ ¦ L---- ¦ ¦ ¦ L---------------------
L----- ¦ L-----
¦
Метод A показывает сложный снимок. Снимок в базе данных II
показывает эффективную производительность запроса, потому что
операция соединения уже была осуществлена во время освежения
снимка. Однако освежения снимка здесь должны быть полными, так
как это сложный снимок.
Метод B показывает два простых снимка в базе данных II, а также
обзор, который осуществляет их соединение в базе данных снимка.
Производительность запросов по этому обзору будет не столь
хороша, как производительность запросов по сложному снимку в
методе A. Однако простые снимки могут освежаться более
эффективно с помощью журналов снимков.
Таким образом, вы можете опираться на следующие факторы:
* Если вы освежаетесь редко и хотите повысить
производительность запросов, используйте метод A.
* Если вы освежаетесь регулярно и можете несколько уступить
в производительности запросов за счет ускорения
освежений, используйте метод B.
----------------
Создание журнала снимков для простых снимков
Создание журнала снимков уменьшает объем обработки и время,
необходимое для освежения простого снимка. Журналы снимков не
могут использоваться со сложными снимками. Журнал снимков
ассоциируется с единственной главной таблицей; аналогично,
главная таблица может иметь лишь один журнал снимков. Если на
одной и той же главной таблице базируются несколько простых
снимков, все они используют тот же самый журнал снимков.
Создавайте журнал снимков в одной базе данных с главной
таблицей, используя команду SQL CREATE SNAPSHOT LOG. Вы можете
установить опции памяти для блоков данных, размеров и
распределения экстентов, а также табличное пространство для
журнала снимков. Например, следующее предложение создает журнал
снимков, ассоциированный с таблицей EMP:
CREATE SNAPSHOT LOG ON emp
TABLESPACE users
STORAGE (INITIAL 10K NEXT 10K PCTINCREASE 50);
Именование журналов снимков
---------------------------
ORACLE автоматически создает журнал снимков в той схеме, которая
содержит главную таблицу. Вы не можете специфицировать имя для
журнала снимков (это имя неявно дается ORACLE); поэтому вопросы
уникальности имени не возникают.
Привилегии, требуемые для создания журналов снимков
---------------------------------------------------
Если вы владеете главной таблицей, то для создания журнала
снимков вы должны иметь системные привилегии CREATE TABLE и
CREATE TRIGGER. Если вы создаете журнал снимков для главной
таблицы другого пользователя, то вы должны иметь системные
привилегии CREATE ANY TABLE и CREATE ANY TRIGGER. В любом
случае, владелец журнала снимков должен иметь достаточную квоту
в табличном пространстве, в котором создается этот журнал.
Привилегии, требуемые для создания журнала снимков,
непосредственно определяются привилегиями, необходиыми для
создания объектов, реализующих этот журнал снимков.
Порядок создания простого снимка и журнала снимков
--------------------------------------------------
Если вы создаете простой снимок, более эффективно создать журнал
снимков перед созданием снимка. Рис.12-2 иллюстрирует два
порядка создания.
Рис.12-2
Порядок создания простого снимка и журнала снимков
г====================================¬
¦ г============¬ ------------+----------¬
¦ ¦ ¦ ¦ ¦ ¦
------------T----¦---T-----------T----¦-----T----+-----¬
¦Create Master¦ Create ¦ Create ¦ 1-е ¦ 2-е ¦
A ¦ Table ¦Snapshot¦Snapshot Log¦освежение ¦освежение ¦
L-------------+--------+------------+----------+-----------
-----------+----------+----------+-----------+----------+--------->
Время
--------------T------------T--------T----------T----------¬
¦Create Master¦ Create ¦ Create ¦ 1-е ¦ 2-е ¦
B ¦ Table ¦Snapshot Log¦Snapshot¦освежение ¦освежение ¦
L-----‑-------+---‑--‑-----+---T----+----T-----+----T------
¦ ¦ ¦ ¦ ¦ ¦
¦ ¦ L---------+---------- ¦
¦ L------------+---------------------
L========================-
====== Полное освежение
------ Быстрое освежение
(стрелки указывают на структуры, используемые для освежения)
Заметьте, что при методе A первое освежение снимка не может
использовать журнал, так как журнал не может отразить всех
обновлений, произошедших между созданием снимка и созданием
журнала снимков; поэтому необходимы два полных освежения.
Напротив, метод B требует одного полного освежения (при
создании снимка); последующие освежения могут немедленно
использовать журнал снимков. Если главная таблица велика, или
на одной главной таблице базируются много снимков, то создание
журнала снимков перед созданием снимков может быть намного более
эффективным.
----------------
Использование снимков
Снимки опрашиваются точно так же, как таблица или обзор.
Например, следующее предложение опрашивает снимок с именем EMP:
SELECT * FROM emp;
Так как снимки можно только читать, вы не можете выдавать по
снимкам предложений INSERT, UPDATE или DELETE; если вы сделаете
это, будет возвращена ошибка. Хотя предложения INSERT, UPDATE и
DELETE могли бы быть выданы по базовой таблице снимка, такие
предложения привели бы к нарушению снимка. Никогда не
манипулируйте данными в базовой таблице снимка.
Создание обзоров и синонимов по снимкам
---------------------------------------
На базе снимков можно определять обзоры и синонимы. Следующее
предложение создает обзор по снимку EMP:
CREATE VIEW sales_dept AS
SELECT ename, empno
FROM emp
WHERE deptno = 10;
Привилегии, требуемые для использования снимка
----------------------------------------------
Чтобы опрашивать снимок, вы должны иметь для этого снимка
объектную привилегию SELECT, полученную либо явно, либо через
роль.
----------------
Индексирование снимков
Чтобы увеличить производительность запросов по снимку, вы можете
создавать индексы по этому снимку. Чтобы индексировать столбец
снимка, вы должны создать индекс по нижележащей таблице "SNAP$",
которая была создана для хранения строк этого снимка.
----------------
Удаление снимков
Вы можете удалить снимок независимо от его главной таблицы или
журнала снимков. Чтобы удалить локальный снимок, используйте
команду SQL DROP SNAPSHOT. Например:
DROP SNAPSHOT emp;
Если вы удаляете снимок по главной таблице, который был
единственным, то вы должны также удалить журнал снимков этой
главной таблицы, если он существует.
Привилегии, требуемые для удаления снимков
------------------------------------------
Чтобы удалить снимок, необходимо быть его владельцем или иметь
системные привилегии DROP ANY SNAPSHOT, DROP ANY TABLE и DROP
ANY VIEW.
----------------
Удаление журналов снимков
Вы можете удалить журнал снимков независимо от его главной
таблицы и от существующих снимков. Вы можете решить удалить
журнал снимков по одной из следующих причин:
* Все простые снимки главной таблицы были удалены.
* Все простые снимки главной таблицы должны быть полностью
(а не быстро) обновлены.
Чтобы удалить локальный журнал снимков, используйте команду SQL
DROP SNAPSHOT LOG, например:
DROP SNAPSHOT LOG emp_log;
Привилегии, требуемые для удаления журнала снимков
--------------------------------------------------
Чтобы удалить журнал снимков, необходимо быть владельцем его
главной таблицы или иметь системную привилегию DROP ANY TABLE.
----------------
Альтернативы снимкам таблиц
Если встроенное в ORACLE средство снимков таблиц не отвечает
вашим требованиям по копированию данных между узлами
распределенной базы данных, то вы имеете две альтернативы:
триггеры Триггеры можно использовать для поддержания
дубликатов таблиц на множественных узлах
распределенной базы данных. Каждый такой
дубликат можно обновлять. Обновления дубликатов
автоматически и синхронно (немедленно)
распространяются на другие дубликаты.
ручное Вы можете вручную копировать таблицу между
дублирование узлами распределенной базы данных (например, с
таблиц помощью SQL или утилит экспорта/импорта ORACLE).
Копии главной таблицы будут отражать ее
состояние на момент последнего копирования. Вы
можете спроектировать ваше приложение так, чтобы
автоматизировать этот процесс.
Выбор метода дублирования таблицы
---------------------------------
Выбор правильного метода дублирования таблицы очень важен. Если
вы выберете для вашего приложения некорректный метод, вы можете
ухудшить производительность базы данных или создать для себя
лишнюю работу.
Если дублируемая таблица подвергается значительному объему
обновлений, которые должны отражаться в дубликатах лишь с
некоторой периодичностью, то лучший выбор дают снимки или ручное
копирование; использование триггеров с такой таблицей вызвало бы
ненужное ухудшение производительности.
Если дублируемая таблица редко обновляется и часто опрашивается,
то вы должны выбирать между снимками или триггерами (ручное
копирование таблицы не дает нужной автоматизации). Следующие
секции обсуждают некоторые вопросы, которые должны
рассматриваться при выборе между снимками и триггерами для
дублирования конкретной таблицы.
Синхронное и асинхронное дублирование
Если обновления дублируемой таблицы должны всегда отражать
текущее состояние этой таблицы, то следует предпочесть
синхронное дублирование таблицы с помощью триггеров. Однако,
если данная таблица обновляется редко (как, например, таблицы
истории), то следует предпочесть снимки - их легче реализовать,
и они столь же эффективны, как и триггеры.
Если вы решили использовать асинхронное дублирование таблицы
(снимки), то довольно вероятно (хотя и не гарантировано), что
различные дубликаты таблицы будут согласованы между собой,
потому что копии должны обновляться в одно и то же время.
Эффективность триггеров и сетевые отказы
Если вы решили использовать триггеры для дублирования таблицы,
имейте в виду, что сетевые сбои ограничивают автономность
каждого узла, вовлекаемого в дублирование таблицы. Если сеть
неработоспособна, распределенные предложения в триггере не могут
выполняться, заставляя триггер возбуждать исключение; если это
исключение явно не обрабатывается триггером, то сам триггер и
предложение, активизировавшее его, подвергнутся откату. Таким
образом, ни явную, ни удаленную таблицу нельзя обновлять, пока
триггеры, вовлеченные в дублирование этой таблицы,
неработоспособны.
Напротив, снимки освежаются периодически. Если сеть не работает
к моменту очередного освежения, то снимки могут быть освежены
позже. Что еще более важно, автономность каждого узла
поддерживается на более высоком уровне, когда для дублирования
таблиц применяются снимки.
Различия в производительности
Снимки могут потенциально обеспечить лучшую производительность,
нежели триггеры. Снимки освежаются периодически, так что за
одну операцию проводится много обновлений. Напротив,
дублирование таблицы с помощью триггеров заставляет обновлять
все копии при каждом обновлении любой из копий таблицы. Поэтому
при высоком количестве обновлений снимки эффективнее триггеров,
ибо при снимках в одной операции концентрируется много
обновлений, что снижает интенсивность сетевого трафика и требует
меньше операций двухфазного подтверждения.
Декларативное определение против процедурного
Реализация дублирования таблицы с помощью снимков довольно
проста; эта реализация чисто декларативна. Напротив, триггеры
нужно писать и отлаживать; это добавляет ненужную сложность,
если только приложению не требуются именно те свойства
дублирования таблицы, которые обеспечиваются триггерами.
Альтернативы снимкам
--------------------
Следующие секции объясняют каждую из двух альтернатив снимкам
таблиц.
Дублирование таблиц с помощью триггеров
Вы можете написать триггеры, чтобы реализовать синхронное
дублирование двух или более таблиц между узлами распределенной
базы данных. Такое дублирование обладает следующими
характеристиками:
* Каждая копия может как опрашиваться, так и обновляться, и
любые обновления немедленно распространяются на все
копии. Если такие требования для вас являются основными,
то вы должны реализовывать дублирование таблиц с помощью
триггеров.
* Удаленные обновления, осуществляемые триггерами,
подтверждаются транзакцией пользователя, содержащей
предложение UPDATE (активизирующей триггер), посредством
обычного двухфазного commit.
* Пока дублирующие триггеры выключены (например, на время
массовой загрузки данных), операции дублирования не
применяются. Поэтому к моменту последующего включения
таких триггеров копии дублируемой таблицы уже не будут
чистыми копиями друг друга.
* Если сетевой сбой прерывает связь между двумя узлами,
содержащими дубликаты таблицы, то ни локальную, ни
удаленные копии этой таблицы нельзя обновлять, пока не
будет устранен сбой; это потенциально ограничивает
возможности обновления дублируемых таблиц.
Шаги по организации дублирования таблицы с помощью триггеров
Если вы решили использовать триггеры для реализации дублирования
таблицы, то вы должны осуществить следующие шаги:
1. Копируемая таблица должна иметь первичный ключ.
2. Создайте флажковый столбец для каждой копии, с типом данных
CHAR(1). Такой столбец необходим для предотвращения
зацикливания каскада триггеров. Например, если вы обновляете
таблицу EMP@NY, будет возбужден триггер для обновления
таблицы EMP@SF. Однако, когда триггер обновляет EMP@SF, вы
не хотите снова обновлять EMP@NY. Флажковый столбец
используется для указания того, какие копии уже обновлены как
результат первоначального предложения, возбудившего триггер.
3. Создайте по каждой копии таблицы локальные обзоры, которые
будут скрывать наличие флажкового столбца от конечных
пользователей.
4. Создайте необходимые связи баз данных в каждой базе данных,
содержащей копию таблицы, если это еще не сделано.
5. Создайте триггеры дублирования по каждой копии таблицы.
Следующие примеры демонстрируют триггеры, которые необходимы
для поддержания двух идентичных таблиц: EMP_BASE@NY и
EMP_BASE@SF. Для простоты предполагается, что таблица
EMP_BASE на каждом узле содержит три столбца: EMPNO, DEPTNO и
FLAG.
В Нью-Йорке (NY):
CREATE TRIGGER emp_ins
AFTER INSERT ON emp_base
FOR EACH ROW
WHEN (new.flag IS NULL)
BEGIN
-- флаг пуст, т.е. наша вставка; продвинуть ее в SF
INSERT INTO fred.emp_base@sf
VALUES(:new.empno, :new.deptno, 'T');
END;
/
CREATE TRIGGER emp_upd
AFTER UPDATE ON emp_base
FOR EACH ROW
BEGIN
IF NOT updating('flag') THEN -- пользовательское обновление; продвинуть его в SF
UPDATE fred.emp_base@sf SET
empno = :new.empno,
deptno = :new.deptno,
flag = 'T' -- триггер всегда обновляет флаг
WHERE empno = :old.empno;
END IF;
END;
/
CREATE TRIGGER emp_del
AFTER DELETE ON emp_base
FOR EACH ROW
DECLARE
mutating EXCEPTION;
PRAGMA exception_init (mutating, -4091);
BEGIN
DELETE fred.emp_base@sf WHERE empno = :old.empno;
EXCEPTION
WHEN mutating THEN NULL;
END;
/
В Сан-Франциско (SF) создаются такие же три триггера, с той
разницей, что "EMP@SF" заменяется на "EMP@NY".
Этот пример позволяет модифицировать лишь по одной строке в
каждый момент. Вы могли бы написать более сложный триггер,
который позволил бы дублировать множественные обновления,
сохраняя их во временной таблице и откладывая все сетевые
операции до конца исполнения предложения.
Ручное копирование таблиц между узлами распределенной базы данных
Вы можете вручную дублировать таблицы между узлами
распределенной базы данных. Дублирование таблиц вручную
часто бывает правильным выбором, если главная таблица
подвергается частым обновлениям, в то время как для
только-читаемых ее дубликатов достаточно лишь время от
времени (например, раз в день) отражать изменения главной
таблицы. В этой ситуации можно избежать конфигураций,
создаваемых для дублирования таблицы через снимки. Вы должны
обсудить это решение с тем лицом, которое будет
администрировать ваше приложение.