Как перенести табличное пространство из базы в базу

Владимир Пржиялковский

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

Итак, посмотрим, как можно быстро перенести из базы в базу табличное пространство целиком. Возможность Oracle, которая при этом используется, носит оригинальное название transportable tablespace. Технически эта возможность реализуется переносом

  • описаний всех пользовательских данных в табличном пространстве - средствами программ exp и imp, а также
  • самих файлов с данными - средствами файловой системы.

Постановка задачи

Пусть имеются две БД: DOLLY и DOLLY1, работающие в ОС Windows NT под управлением СУБД Oracle версии 8.1.7. В БД DOLLY имеется пользователь DNA, имеющий какие-то объекты в табличном пространстве HEART. Покажем, как это табличное пространство можно перенести в базу DOLLY1. После этого сделаем изменения в пространстве HEART и выполним обратный перенос.

То, что пример приводится для Windows NT, вовсе не критично и оговаривается здесь лишь для оправдания синтаксиса имен файлов, а также во избежание недоразумений.

Выход на исходные позиции: подготовка тренировочных баз

Если Вы работаете на одной машине, удобно будет завести на терминале два консольных окошка: первое , настроенное на работу с БД DOLLY и второе , настроенное на DOLLY1.

В первом окошке войдем в SQL*Plus от имени SYS и наберем

CREATE TABLESPACE heart 
DATAFILE ‘d:\oracle\oradata\dolly\heart1.dbf’ SIZE 1M;

CREATE USER dna IDENTIFIED BY dna
DEFAULT TABLESPACE heart TEMPORARY TABLESPACE temp;

GRANT CONNECT, RESOURCE TO dna;

Во втором окошке от имени SYS наберем в SQL*Plus

CREATE USER dna IDENTIFIED BY dna;

GRANT CONNECT, RESOURCE TO dna;
Комментарий. С помощью команды GRANT новым пользователям полномочия были выданы посредством ролей CONNECT и RESOURCE. Это удобно для примера, однако не стоит забывать, что в рабочей БД необходимо иметь существенно более продуманную и регламентированную систему раздачи полномочий.

Снова в первом окошке от имени SCOTT наберем

GRANT SELECT ON emp TO dna;
CONNECT dna/dna
CREATE TABLE empa AS SELECT * FROM scott.emp;

Теперь у DOLLY в HEART завелось 14 человек - если, конечно, в типовой схеме SCOTT Вы ничего не меняли. Наша задача - перенести HEART из DOLLY в DOLLY1, а значит и перенести туда же этих сотрудников.

Переносим табличное пространство из первой базы во вторую

Прежде чем делать сам перенос, нужно убедиться в том, что переносимое табличное пространство - замкнутое, то есть не имеет связей с прочими табличными пространствами. Иначе перенос такого пространства был бы некорректен. Для такой проверки имеется процедура TRANSPORT_SET_CHECK в системном пакете DBMS_TTS. От имени SYS выдадим в первом окошке последовательно:

EXEC DBMS_TTS.TRANSPORT_SET_CHECK( -
 ts_list => ‘HEART’, -
 incl_constraints => TRUE)
SELECT * FROM TRANSPORT_SET_VIOLATIONS;

Последний SELECT - это проверка результата отработки непосредственно предшествующей процедуры. В нашем случае проверка даст пустое множество, однако если бы табличное пространство HEARTS имело внешние связи, в специальную системную выводимую таблицу SYS.TRANSPORT_SET_VIOLATIONS поступил бы их перечень, и эта таблица не была бы пуста.

Комментарий. Название первого параметра процедуры TRANSPORT_SET_CHECK намекает на то, что в нем может указываться список табличных пространств, а не отдельное пространство, как в нашем случае. Это правда. Например, мы могли бы хранить в одном пространстве таблицы, а в другом - их индексы. У этих пространств по определению будут "межтабличные связи", поэтому по отдельности переносить их будет невозможно, а, в то же время, вдвоем - вполне допустимо. В этом случае в параметре ts_list нужно будет их привести через запятую, и будет проверена замкнутость пары пространств.

Второй параметр процедуры нужно установить в TRUE, если данные планируется передавать вместе с ограничениями целостности, и FALSE - в противном случае.

Функционально идентичной процедуре TRANSPORT_SET_CHECK должна быть булева функция ISSELFCONTAINED с теми же параметрами. Она не описана в документации, но в коде приложения может оказаться удобнее.

Теперь можно выдать:

ALTER TABLESPACE HEART READ ONLY;
HOST EXP TRANSPORT_TABLESPACE=Y TABLESPACES=(HEART) -
CONSTRAINTS=N GRANTS=Y TRIGGERS=N FILE=DHEART.DMP

Здесь понадобится в диалоге указать пользователя, выполняющего этот специфичный вид экспорта. Например, INTERNAL/ORACLE AS SYSDBA, или же другого пользователя, обладающего полномочием (grant) EXECUTE_CATALOG_ROLE. Пользователь SYS этим полномочием изначально обладает.

Теперь на уровне файловой системы скопирует файл heart1.dbf из d:\oracle\oradata\dolly в d:\oracle\oradata\dolly1.

Прежде, чем покинуть первое окошко, не забудем выдать

ALTER TABLESPACE HEART READ WRITE;

Во втором окошке от имени SYS наберем:

CREATE USER dna IDENTIFIED BY dna;
GRANT CONNECT, RESOURCE TO dna;
HOST IMP TRANSPORT_TABLESPACE=Y -
DATAFILES=(d:\oracle\oradata\dolly1\heart1.dbf)
FILE=DHEART.DMP

Снова в диалоге указываем INTERNAL/ORACLE AS SYSDBA. Как только все проработает, данные перенесены. Не помешает, однако, выполнить еще

ALTER TABLESPACE HEART READ WRITE;
ALTER USER dna DEFAULT TABLESPACE heart TEMPORARY
TABLESPACE temp;

Табличное пространство в DOLLY1 полностью готово к эксплуатации.

Переносим табличное пространство из второй базы в первую

Наберем для проверки во втором окошке от имени dna

INSERT INTO empa SELECT * from empa;
COMMIT;
SELECT * from empa;

У DOLLY в HEART образовалось в два раза больше человек: 28.

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

DROP TABLESPACE hearts INCLUDING CONTENTS;

А дальше - все, как и раньше; во втором окошке:

EXEC DBMS_TTS.TRANSPORT_SET_CHECK( -
 ts_list => ‘HEART’, -
 incl_constraints => FALSE)
SELECT * FROM TRANSPORT_SET_VIOLATIONS;
ALTER TABLESPACE HEART READ ONLY;
HOST EXP TRANSPORT_TABLESPACE=Y TABLESPACES=(HEART)
FILE=DHEART.DMP

… Здесь прервемся и скопируем файл файл heart1.dbf из d:\oracle\oradata\dolly1 в d:\oracle\oradata\dolly ...

ALTER TABLESPACE HEART READ WRITE;

Переключаемся на первое окошко и пользователя SYS:

HOST IMP TRANSPORT_TABLESPACE=Y -
DATAFILES=(d:\oracle\oradata\dolly\heart1.dbf)
FILE=DHEART.DMP

Укажем в диалоге INTERNAL/ORACLE AS SYSDBA, ждем конца подключения пространства системой и выполняем

ALTER TABLESPACE HEART READ WRITE;

Все. Можно проверять, сколько людей у DOLLY.

О чем не было сказано, но стоит упомянуть

Прежде всего нужно сказать, что в одной БД после экспорта, а в другой - после импорта, нужно выполнить резервное копирование контрольного файла; можно в облегченном варианте:

ALTER DATABASE BACKUP CONTROLFILE TO TRACE;

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

В-третьих, о возможностях такого метода. Переносить табличные пространства можно между любыми двумя БД, работающими под управлением одной версии СУБД на одной платформе. Разумный пример использования подхода предлагает фирма Oracle: это тиражирование данных БД с помощью CD-ROM.

Есть и некоторые ограничения по части содержания, например, переносимый набор табличных пространств не должен (в текущих версиях Oracle) иметь в себе "фотоснимки" (snapshots, разновидность materialized view); индексы, построенные с использованием функционального преобразования; очереди в смысле advanced queue; некоторые другие более специальные виды объектов.

Ссылки по теме

Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=1783