On-Line Библиотека www.XServer.ru - учебники, книги, статьи, документация, нормативная литература.
       Главная         В избранное         Контакты        Карта сайта   
    Навигация XServer.ru


Самая подробная информация европласт лепнина тут.




 

Перемещаем табличные пространства

Валерий Юринский,
ORACLE Certified Professional

Сервер Oracle8i предоставляет новую возможность быстрого обмена большими объемами информации между базами данных Oracle - перемещаемые табличные пространства (transportable tablespaces). Некоторым аспектам практического применения этой возможности посвящена эта статья.

Преимущества и ограничения

Как всегда возникают вопросы:

  • А что мы с этого будем иметь?
  • Кому, что и как это облегчает и усложняет?

Вот лишь некоторые ответы. Перемещаемые табличные пространства обеспечивают:

  • Оперативное предоставление разработчикам свежей копии данных производственной системы.
  • Использование информации, публикуемой на неперезаписываемых носителях (CD-ROM, DVD и т.п.).
  • Быстрое перемещение данных из оперативной системы в хранилище или в витрину данных.

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

Существует ряд условий ограничивающих применение описываемой возможности.

1) "Донором" может быть только Oracle8i Enterprise Edition. "Приёмником" - любой вариант сервера Oracle8i: Enterprise/Standard/Personal Edition.

Проверить поддерживает ли ваша система создание набора перемещаемых табличных пространств можно выполнив запрос:

SELECT * FROM v$option

WHERE UPPER(parameter) =
'EXPORT TRANSPORTABLE TABLESPACES'

/

Все в порядке, если в результате будет получено:

PARAMETER VALUE

-------------------------------- -----

Export transportable tablespaces TRUE

2) Можно перемещать табличные пространства только между такими базами данных Oracle8i, которые:

  • имеют одинаковый размер блока (db_block_size),
  • созданы с одинаковой кодировкой (character set),
  • в файлах инициализации (INIT.ORA) исходной и целевых баз данных параметр COMPATIBLE должен быть установлен в значение 8.1,
  • работают на совместимых платформах одного и того же производителя оборудования.

Удовлетворение первых трех требований можно проверить, выполнив в исходной и целевой БД (результаты должны быть идентичны) запрос:

SELECT name, value FROM v$parameter

WHERE name IN ('db_block_size','compatible')

UNION ALL

SELECT parameter, value FROM nls_database_parameters

WHERE parameter LIKE '%CHARACTERSET'

/

NAME VALUE

--------------------- ------------

db_block_size 4096

compatible 8.1.0

NLS_CHARACTERSET CL8MSWIN1251

NLS_NCHAR_CHARACTERSET CL8MSWIN1251

3) В целевой базе данных не должно быть табличного пространства с таким же именем, как у подключаемого.

4) Не поддерживается транспортировка:

  • снапшотов и тиражируемых таблиц (Snapshot/replication),
  • Функциональных индексов (Function-based indexes),
  • локальных ссылок на объекты (Scoped REFs),
  • доменных индексов (Domain indexes) (новый тип индексов, предоставляющих возможность расширенного индексирования),
  • совместимых с v8.0 улучшенных очередей (advanced queues) с множественными получателями (recipients).

Как это сделать

Предположим, что нам нужно перенести данные таблицы EMP, созданной следующим образом:

DROP TABLE emp

/

DROP TABLE dept

/

CREATE TABLE dept (

deptno NUMBER(2)

, dname VARCHAR2(14) CONSTRAINT dept#N#dname NOT NULL

, loc VARCHAR2(13) CONSTRAINT dept#N#loc NOT NULL

, CONSTRAINT dept#p PRIMARY KEY(deptno)

USING INDEX TABLESPACE indx

)

TABLESPACE users

/

GRANT SELECT, INSERT, UPDATE, DELETE ON
dept TO emp_manager

/

CREATE TABLE emp (

empno NUMBER(4)

, ename VARCHAR2(10) CONSTRAINT emp#N#ename NOT NULL

, job VARCHAR2(9) CONSTRAINT emp#N#job NOT NULL

, mgr NUMBER(4)

, hiredate DATE CONSTRAINT emp#N#hiredate NOT NULL

, sal NUMBER(7,2) CONSTRAINT emp#N#sal NOT NULL

, comm NUMBER(7,2)

, deptno NUMBER(2) CONSTRAINT emp#N#deptno NOT NULL

, CONSTRAINT emp#p PRIMARY KEY (empno)

USING INDEX TABLESPACE indx

, CONSTRAINT emp#r#dept FOREIGN KEY (deptno)

REFERENCES dept(deptno)

, CONSTRAINT emp#r#emp FOREIGN KEY (mgr)

REFERENCES emp(empno)

)

TABLESPACE user_data

/

GRANT SELECT, INSERT, UPDATE, DELETE
ON emp TO emp_manager

/

CREATE TRIGGER emp#BIU#R

BEFORE INSERT OR UPDATE ON EMP FOR EACH ROW

BEGIN

:NEW.ename := UPPER(:NEW.ename);

END;

/

Шаг 1. Выбор самодостаточного набора табличных пространств

Самодостаточный (self-contained) набор табличных пространств - это совокупность табличных пространств, объекты которых не ссылаются на какие-либо объекты, не содержащиеся в данном наборе. В качестве примеров нарушений самодостаточности можно привести случаи, когда:

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

Для проверки самодостаточности удобно использовать процедуру TRANSPORT_SET_CHECK из пакета SYS.DBMS_TTS (общего синонима нет). Пользователю должна быть предоставлена роль EXECUTE_CATALOG_ROLE (изначально такая роль предоставлена SYS).

BEGIN

sys.dbms_tts.transport_set_check (

-- Список табличных пространств

ts_list => 'USER_DATA'

-- Учитывать ссылочные ограничения

, incl_constraints => TRUE);

END;

/

Результаты ее работы записываются во временную таблицу и их можно посмотреть через системное представление SYS.TRANSPORT_SET_VIOLATIONS (общего синонима также нет):

SELECT * FROM sys.transport_set_violations

/

VIOLATIONS

---------------------------------

[1] Constraint EMP#N#ENAME between table SCOTT.DEPT
in tablespace USERS and table SCOTT.EMP
in tablespace USER_DATA

[2] Constraint EMP#N#JOB between table SCOTT.DEPT
in tablespace USERS and table SCOTT.EMP
in tablespace USER_DATA

[3] Constraint EMP#N#HIREDATE between table SCOTT.DEPT
in tablespace USERS and table SCOTT.EMP
in tablespace USER_DATA


[4]
Constraint EMP#N#SAL between table SCOTT.DEPT
in tablespace USERS and table SCOTT.EMP
in tablespace USER_DATA


[5]
Constraint EMP#N#DEPTNO between table SCOTT.DEPT
in tablespace USERS and table SCOTT.EMP
in tablespace USER_DATA


[6]
Constraint EMP#P between table SCOTT.DEPT
in tablespace USERS and table SCOTT.EMP
in tablespace USER_DATA


[7]
Constraint EMP#R#DEPT between table SCOTT.DEPT
in tablespace

USERS and table SCOTT.EMP
in tablespace USER_DATA


[8]
Constraint EMP#R#EMP between table SCOTT.DEPT
in tablespace USERS and table SCOTT.EMP
in tablespace USER_DATA

Выявленные нарушения 1-5 и 8 вызывают некоторое недоумение, поскольку связаны с ограничениями типа NOT NULL таблицы EMP, ее первичным ключом и ссылкой самой на себя, что вроде бы никак не связанно с табличными пространствами, отличными USER_DATA (может быть это оттого, что сведения о них хранятся в словаре данных?

Если вы получите сообщение вида:

Master table SCOTT.EMP in tablespace USER_DATA
not allowed in transportable set

ищите снапшот, использующий указанную таблицу.

Диагностика подобная:

Partitioned table SCOTT.ORDER_DETAILS is partially
contained in the transportable set

свидетельствует о том, что транспортируемый набор содержит не все разделы секционированной таблицы SCOTT.ORDER_DETAILS.

Нарушение 7 напоминает о том, что EMP имеет ссылку на таблицу DEPT, поэтому добавим в список табличное пространство USERS, в котором создана DEPT:

BEGIN

sys.dbms_tts.transport_set_check (

ts_list => 'USER_DATA, USERS',

incl_constraints => TRUE);

END;

/

Выборка из SYS.TRANSPORT_SET_VIOLATIONS не возвращает строк, то есть все в порядке. Однако, если вы хотите перенести и индексы (возможно не все), то для выявления таблиц, имеющих индексы, расположенные в табличных пространствах, не входящих в набор, подлежащий транспортировке выполните:

SELECT table_name, tablespace_name FROM dba_indexes

WHERE table_name IN

(SELECT table_name FROM dba_tables

WHERE tablespace_name IN ('USER_DATA','USERS'))

MINUS

SELECT table_name, tablespace_name FROM dba_tables

WHERE tablespace_name NOT IN ('USER_DATA','USERS')

/

Для данного примера в результате получим:

TABLE_NAME TABLESPACE_NAME

---------- ---------------

EMP INDX

DEPT INDX

Внимание! Для секционированных (partitioned) таблиц и индексов, а также для индекс-таблиц (index organized tables), запрос следует модифицировать с учетом соответствующих представлений словаря данных!

На этом этапе будет также уместным определить:

  • файлы данных, подлежащие переподключению:

SELECT tablespace_name, file_name

FROM dba_data_files

WHERE tablespace_name IN ('USER_DATA','USERS', 'INDX')

ORDER BY tablespace_name, file_name

/

TABLESPACE_NAME FILE_NAME

--------------- -----------------------------------

INDX D:\ORACLE81\ORADATA\VSUIMB\INDX01.ORA

USERS D:\ORACLE81\ORADATA\VSUIMB\USERS01.ORA

USER_DATA D:\ORACLE81\ORADATA\VSUIMB\USER_DATA_01.ORA

  • имена схем данных, которым принадлежат таблицы и индексы, расположенные в транспортируемом наборе:

SELECT owner, segment_type, COUNT(*) AS cnt

FROM dba_segments

WHERE tablespace_name IN ('USER_DATA','USERS', 'INDX')

GROUP BY owner, segment_type

/

OWNER SEGMENT_TYPE CNT

----- ------------ -------

SCOTT INDEX 2

SCOTT TABLE 2

SYSTEM TABLE 1

TOAD INDEX 4

TOAD TABLE 3

  • роли и/или пользователей, которым предоставлены привилегии доступа к таблицам, расположенным в перемещаемых табличных пространствах:

SELECT DISTINCT P.owner AS table_owner

, P.grantee

, DECODE(U.type#, 0, 'ROLE', 1, 'USER') as grantee_type

FROM dba_tab_privs P, sys.user$ U

WHERE (P.owner, P.table_name) IN

(SELECT owner, segment_name

FROM dba_segments

WHERE tablespace_name IN ('USER_DATA','USERS', 'INDX'))

AND P.grantee = U.name

/

TABLE_OWNER GRANTEE GRANTEE_TYPE

----------- ------------ ------------

SCOTT EMP_MANAGER ROLE

SYSTEM PUBLIC ROLE

TOAD PUBLIC ROLE

Кроме того, может быть полезным выявление триггеров, не принадлежащих собственникам таблиц:

SELECT DISTINCT owner AS trigger_owner

, table_owner

FROM dba_triggers

WHERE (table_owner, table_name) IN

(SELECT owner, segment_name

FROM dba_segments

WHERE tablespace_name IN ('USER_DATA','USERS', 'INDX'))

AND owner <> table_owner

/


что может в результате дать, например:

TRIGGER_OWNER TABLE_OWNER

------------- -----------

FILER SCOTT

Шаг 2. Создание самодостаточного набора табличных пространств

1. Сначала следует перевести табличные пространства набора в состояние ТОЛЬКО ЧТЕНИЕ (READ ONLY):

ALTER TABLESPACE user_data READ ONLY;

ALTER TABLESPACE users READ ONLY;

ALTER TABLESPACE indx READ ONLY;

2. Затем с помощью утилиты EXP экспортируются метаданные словаря. Например:

EXP TRANSPORT_TABLESPACE=Y
TABLESPACES=(USERS, USER_DATA, INDX) TRIGGERS=Y
CONSTRAINTS=Y GRANTS=Y FILE=exp_tts log=exp_tts

Параметры:

  • TRANSPORT_TABLESPACE=Y - указывает, что выполняется экспорт метаданных транспортируемых табличных пространств,
  • TABLESPACES=(USERS, USER_DATA, INDX) - задает список транспортируемых табличных пространств,
  • TRIGGERS=Y - Экспортировать табличные триггеры (если указать N, то триггеры экспортироваться не будут)
  • CONSTRAINTS=Y - Экспортировать ограничения целостности (при N не экспортируются ограничения типов PRIMARY KEY, UNIQUE, FOREIGN KEY и CHECK, однако ограничения NOT NULL экспортируются),
  • GRANTS=Y - Экспортировать привилегии доступа к таблицам (N отменяет экспорт привилегий),
  • FILE=exp_tts и log=exp_tts имя файла с данными и имя файла журнала экспорта.

При запросе имени, согласно документации, следует подключаться к базе данных как SYSDBA:

Username: SYS@VSUIMB AS SYSDBA

Password:

Впрочем, USERID=SYS@VSUIMB AS SYSDBA, как и все прочие параметры можно задать в отдельном файле параметров, указав его при вызове утилиты (EXP PARFILE=file_name.par). Кроме того, натурные испытания показали, что на данном этапе подключаться как SYSDBA вовсе не обязательно - достаточно роли DBA.

3. Сделать копии файлов данных в другое место на той же вычислительной установке или на транспортируемый носитель или на машину, где расположена целевая БД.

4. Не забудьте перевести табличные пространства назад в состояние ЧТЕНИЕ-ЗАПИСЬ (Если это необходимо для продолжения нормальной работы пользователей исходной БД):

ALTER TABLESPACE user_data READ WRITE;

ALTER TABLESPACE users READ WRITE;

ALTER TABLESPACE indx READ WRITE;

Шаг 3. Перенос набора табличных пространств

Этот шаг предельно прост.

Переносим копии файлов данных и файл, полученный утилитой экспорта, в место, доступное целевой базе данных. Это можно сделать любым доступным способом: утилитой ОС, по FTP, публикацией на неперезаписываемом носителе и т.п.

Содержимое файла экспорта метаданных можно посмотреть с помощью команды:

IMP TRANSPORT_TABLESPACE=Y FILE=exp_tts log=list_tts
indexfile=list_tts show=Y

В фрагменте полученного файла list_tts.sql, содержащем информацию о таблице DEPT обнаруживаем неописанные в документации служебные метапараметры SEG_FILE, SEG_BLOCK и OBJNO_REUSE:

REM CREATE TABLE "SCOTT"."DEPT" ("DEPTNO" NUMBER(2, 0),

REM "DNAME" VARCHAR2(14) CONSTRAINT "DEPT#N#DNAME"

REM NOT NULL ENABLE, "LOC" VARCHAR2(13)

REM CONSTRAINT "DEPT#N#LOC" NOT NULL ENABLE)

REM PCTFREE 10 PCTUSED 40 INITRANS 1

REM MAXTRANS 255 LOGGING

REM STORAGE(SEG_FILE 3 SEG_BLOCK 2992 OBJNO_REUSE 14780

REM INITIAL 53248 NEXT 53248 MINEXTENTS 1

REM MAXEXTENTS 2147483645

REM PCTINCREASE 1 FREELISTS 1 FREELIST GROUPS 1

REM BUFFER_POOL DEFAULT) TABLESPACE "USERS" ;

Шаг 4. Подключение набора табличных пространств к целевой БД

Перед тем, как приступить собственно к подключению (plug-in) может потребоваться создание:

  • схем данных, которым будут принадлежать таблицы, индексы, триггеры перемещаемого набора,
  • пользователей и/или ролей, которым будут предоставлены привилегии доступа к таблицам.

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

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

IMP PARFILE=imp_tts.par


Файл imp_tts.par:

USERID=SYS@SVORA AS SYSDBA

TRANSPORT_TABLESPACE=Y

DATAFILES=('G:\ORACLE816\ORADATA\SVORAPLUG\INDX01.ORA',


'G:\ORACLE816\ORADATA\SVORAPLUG\USERS01.ORA',


'G:\ORACLE816\ORADATA\SVORAPLUG\USER_DATA_01.ORA')

TABLESPACES=(USERS,USER_DATA,INDX)

TTS_OWNERS=(SCOTT,SYSTEM,TOAD)

FROMUSER=(SCOTT,SYSTEM,TOAD)

TOUSER=(TIGER,MANAGER,PANDORA)

FILE=exp_tts.dmp

LOG=imp_tts.log

Здесь:

  • TRANSPORT_TABLESPACE=Y - указывает, что импортируются метаданные набора подключаемых табличных пространств,
  • DATAFILES=(:) - список, определяющий имена и место расположения подключаемых файлов данных,
  • TABLESPACES=(USERS,USER_DATA,INDX) - список табличных пространств. Если параметр не задан, то список берется из файла экспорта. Если задан, то сверяется со списком, содержащимся в файле экспорта (в случае несовпадения будет выдано сообщение об ошибке).
  • TTS_OWNERS=(SCOTT,SYSTEM,TOAD) - список схем, которым принадлежат объекты в подключаемых табличных пространствах. Если параметр не задан, то список берется из файла экспорта. Если задан, то сверяется со списком, содержащимся в файле экспорта (в случае несовпадения будет выдано сообщение об ошибке).
  • FROMUSER=(SCOTT,SYSTEM,TOAD) , TOUSER=(TIGER,MANAGER,PANDORA) - имена исходных и соответствующих им целевых схем. В этом примере объекты, принадлежавшие в исходной БД схеме SCOTT, будут импортированы в схему TIGER, принадлежавшие SYSTEM в схему MANAGER, а TOAD в PANDORA. Если параметры опущены, то данные будут импортироваться в одноименные схемы (SCOTT в SCOTT и т.д.)

Что еще нужно сделать, если схема клонируется для разработчиков

Транспортируемые табличные пространства предоставляют разработчикам возможность получить копию части данных производственной системы, тождественных не только по содержанию, но и по физическим характеристикам (фрагментация). Однако для этого в дополнение к перечисленному выше потребуется выполнить некоторые дополнительные действия. Дело в том, что при транспортировке метаданных не экспортируются представления (view), процедуры, функции, пакеты и др. Поэтому их нужно переносить отдельно. Для этого удобнее всего воспользоваться всё тем же экспортом-импортом. Допустим, что все интересующие нас объекты принадлежат схеме SCOTT. Тогда команда экспорта в из исходной БД могла бы выглядеть так:

EXP SCOTT/TIGER@VSUIMB FILE=scott_proc log=scott_proc ROWS=N

Воссоздадим недостающие объекты в целевой базе данных, воспользовавшись при импорте в схему TIGER командой:

IMP TIGER/KING@SVORA FILE=scott_proc log=scott_proc_IMP IGNORE=Y

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

О чем следует помнить

После успешного подключения набора табличных пространств к целевой базе данных не забудьте, как уже говорилось выше, перевести табличные пространства исходной БД в состояние READ WRITE, если это необходимо для работы её пользователей.

  • После подключения табличного пространства ROWID строк содержащихся в нем таблиц больше в целом не уникален в рамках БД назначения, но по-прежнему уникален в рамках таблицы. Вероятно, то же происходит с идентификатором объекта БД (см. выше OBJNO_REUSE).
  • При импорте Oracle не контролирует объектные ссылки и поэтому возможно появление зависших (dangling) REFs.
  • Аналогично не контролируется наличие внешних двоичных файлов, на которые указывают ссылки BFILE.
  • Если используемые в коде триггера объекты отсутствуют, то при импорте триггеров возможны ошибки компиляции.
  • Ну и никогда не следует забывать, что любая новая возможность, кроме всего прочего, всегда предоставляет пищу для пытливого ума и непоседливых рук. Поэтому, перефразируя известную пословицу и клятву, повторим главную заповедь "администрата": "Не навреди! Семь пробных баз угробь, а потом на рабочую ставь!"

Такие дела.




Литература по Oracle