четверг, 16 октября 2014 г.

Oracle: Клонирование базы данных

На тему клонирования баз в Oracle, вообще говоря, только ленивый не писал. Каждый недоношенный новообращенный OCA/OCP стремится донести перлы своей мудрости, обычно с орфографическими и грамматическими ошибками, до благодарного человечества.

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

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

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

Краткий пересказ пяти с половиной тысяч предыдущих серий

Клонирование баз - штука весьма распространенная и востребованная.

Причины, по которым это приходится делать, довольно обширны и разнообразны:

  1. Вы выполняете миграцию боевой базы на другой сервер/платформу/архитектуру.
  2. Вам нужно создать тестовый сервер для итеративной разработки.
  3. Вы строите standby.
  4. Вы занимаетесь технической поддержкой и вам нужно тело что-то, на чем можно воспроизвести проблему и заняться паталогоанатомией.
  5. Вы хотите оптимизировать продуктивную БД, но вам нельзя создавать проблемы черепашкам продвинутым пользователям, и вы хотите использовать Real Application Testing на клоне, где и собираетесь провернуть всю оптимизацию прежде, чем испохабите выполните это на продуктиве, легко и непринужденно.
И так далее. 

Во всех случаях, когда вам нужен полный бинарный дубль вашей первичной базы - вам придется пользоваться клонированием, причем с использованием RMAN (Гуй используют только окошечники. Которых бьют. Ногами. Сильно).

Как мы это делаем? Всегда правой!

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


  1. Убедитесь, что на продуктивной системе (ну или там, куда вы будете сваливать полный физический бэкап продуктивной системы) достаточно дискового пространства для размещения этого самого бэкапа.
  2. Убедитесь, что на сервере, где вы будете создавать клон, достаточно места как для размещения полного физического бэкапа продуктивной системы, так и для получившейся базы (а она будет почти равна по размеру продуктивной!) плюс некоторый запас.
  3. Убедитесь, что обе вышеперечисленные системы соединены друг с другом достаточно широким сетевым интерконнектом и по дороге нет какого-нибудь тщедушного коммутатора.
  4. Убедитесь, что у вас надежное консольное соединение с обеими системами.
  5. Установите на сервер для базы-клона ПО Oracle той же самой версии, что и на боевой системе.
Проверили? Тогда приступим.

  1. Выполним на продуктивной системе полное резервное копирование (онлайновое), включив в резервную копию все архивные логи: 

    connect target /
    run{
    configure controlfile autobackup format for device type disk to '/путь_к_точке монтирования_бэкапа/backup/%F';
    configure controlfile autobackup on;
    allocate channel d1 type disk;
    backup tag FULL_DB format '/путь_к_точке монтирования_бэкапа/backup/db_%t_%s.bk' (database) plus archivelog;
    release channel d1;
    }
  2. Желательно написать это в виде скрипта - пригодится еще не раз в будущем.
  3. Скопируем все файлы, произведенные скриптом бэкапа (включая c-* и *.bk) на целевую систему. В точку монтирования с таким же именем, что и в нашей команде (скрипте): /путь_к_точке монтирования_бэкапа/backup
  4. Создадим на целевой системе файл orapw. Стандартной командой.
  5. Создадим на целевой системе файл tnsnames.ora: 


    # tnsnames.ora Network Configuration File: /opt/oracle/product/10.2/db_1/network/admin/tnsnames.ora
    # Generated by Oracle configuration tools.

    PROD =
    (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.50.2)(PORT = 1521))
    (CONNECT_DATA =
    (SERVER = DEDICATED)
    (SERVICE_NAME = PROD)
    )
    )

    TEST =
    (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.50.30)(PORT = 1521))
    (CONNECT_DATA =
    (SERVICE_NAME = TEST)
    )
    )
  6. Создадим на целевой системе файл initTEST.ora. Необходимо убедиться, что значение параметра compatible идентично на продуктивной и клонируемой системах:

    compatible='10.2.0.3.0'
    TEST.__db_cache_size=587202560
    TEST.__java_pool_size=16777216
    TEST.__large_pool_size=16777216
    TEST.__shared_pool_size=956301312
    TEST.__streams_pool_size=16777216
    *.audit_file_dest='/data/TEST/adump'
    *.background_dump_dest='/data/TEST/bdump'
    *.compatible='10.2.0.3.0'
    *.control_files='/data/TEST/control01.ctl','/data/TEST/control02.ctl','/data/TEST/control03.ctl'
    *.core_dump_dest='/data/TEST/cdump'
    *.db_block_size=16384
    *.db_domain=''
    *.db_file_multiblock_read_count=16
    *.db_name='TEST'
    *.db_recovery_file_dest='/data/TEST/flash_recovery_area'
    *.db_recovery_file_dest_size=10485760000
    *.dispatchers='(PROTOCOL=TCP) (SERVICE=TESTXDB)'
    *.job_queue_processes=10
    *.nls_language='RUSSIAN'
    *.nls_territory='RUSSIA'
    *.open_cursors=300
    *.pga_aggregate_target=1672478720
    *.processes=150
    *.remote_login_passwordfile='EXCLUSIVE'
    *.sga_target=1610612736
    *.undo_management='AUTO'
    *.undo_tablespace='UNDOTBS1'
    *.user_dump_dest='/data/TEST/udump'
    DB_FILE_NAME_CONVERT=(/путь_к_точке_монтирования_продуктивной_базы/PROD/,/data/TEST/)
    LOG_FILE_NAME_CONVERT=(/путь_к_точке_монтирования_продуктивной_базы/redologs/PROD/,/data/TEST/)
Дальнейшие действия лучше будет показать в виде лога:


SQL> conn / as sysdba
Connected to an idle instance.
SQL> create spfile from pfile;

File created.

SQL> startup force nomount;
ORACLE instance started.

Total System Global Area 1610612736 bytes
Fixed Size 2084296 bytes
Variable Size 385876536 bytes
Database Buffers 1207959552 bytes
Redo Buffers 14692352 bytes
SQL> Disconnected from Oracle Database 10g Release 10.2.0.4.0 - 64bit Production

oracle@Test:/путь_к_точке монтирования_бэкапа/backup> rman TARGET sys/*****@PROD NOCATALOG AUXILIARY /

Recovery Manager: Release 10.2.0.4.0 - Production on Fri Oct 10 15:18:54 2014

Copyright (c) 1982, 2007, Oracle. All rights reserved.

connected to target database: PROD (DBID=1324970899)
using target database control file instead of recovery catalog
connected to auxiliary database: TEST (not mounted)

RMAN> duplicate target database to TEST;

Starting Duplicate Db at 10-OCT-14
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: sid=156 devtype=DISK

contents of Memory Script:
{
set until scn 90049065;
set newname for datafile 1 to
"/data/TEST/system01.dbf";
set newname for datafile 2 to
"/data/TEST/undotbs01.dbf";
set newname for datafile 3 to
"/data/TEST/sysaux01.dbf";
set newname for datafile 4 to
"/data/TEST/users01.dbf";
restore
check readonly
clone database
;
}
executing Memory Script

executing command: SET until clause

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

Starting restore at 10-OCT-14
using channel ORA_AUX_DISK_1

channel ORA_AUX_DISK_1: starting datafile backupset restore
channel ORA_AUX_DISK_1: specifying datafile(s) to restore from backup set
restoring datafile 00001 to /data/TEST/system01.dbf
restoring datafile 00002 to /data/TEST/undotbs01.dbf
restoring datafile 00003 to /data/TEST/sysaux01.dbf
restoring datafile 00004 to /data/TEST/users01.dbf
channel ORA_AUX_DISK_1: reading from backup piece /datatssd/backup/db_860592108_121.bk
channel ORA_AUX_DISK_1: restored backup piece 1
piece handle=/путь_к_точке монтирования_бэкапа/backup/db_860592108_121.bk tag=FULL_DB
channel ORA_AUX_DISK_1: restore complete, elapsed time: 00:02:27
Finished restore at 10-OCT-14
sql statement: CREATE CONTROLFILE REUSE SET DATABASE "TSSDT" RESETLOGS ARCHIVELOG
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 100
MAXINSTANCES 8
MAXLOGHISTORY 584
LOGFILE
GROUP 1 ( '/data/TEST/redo01.log' ) SIZE 50 M REUSE,
GROUP 2 ( '/data/TEST/redo02.log' ) SIZE 50 M REUSE,
GROUP 3 ( '/data/TEST/redo03.log' ) SIZE 50 M REUSE
DATAFILE
'/data/TEST/system01.dbf'
CHARACTER SET CL8MSWIN1251


contents of Memory Script:
{
switch clone datafile all;
}
executing Memory Script

released channel: ORA_AUX_DISK_1
datafile 2 switched to datafile copy
input datafile copy recid=1 stamp=860599299 filename=/data/TEST/undotbs01.dbf
datafile 3 switched to datafile copy
input datafile copy recid=2 stamp=860599299 filename=/data/TEST/sysaux01.dbf
datafile 4 switched to datafile copy
input datafile copy recid=3 stamp=860599299 filename=/data/TEST/users01.dbf

contents of Memory Script:
{
set until scn 90049065;
recover
clone database
delete archivelog
;
}
executing Memory Script

executing command: SET until clause

Starting recover at 10-OCT-14
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: sid=158 devtype=DISK

starting media recovery

channel ORA_AUX_DISK_1: starting archive log restore to default destination
channel ORA_AUX_DISK_1: restoring archive log
archive log thread=1 sequence=3304
channel ORA_AUX_DISK_1: reading from backup piece /путь_к_точке монтирования_бэкапа/backup/db_860592284_122.bk
channel ORA_AUX_DISK_1: restored backup piece 1
piece handle=/путь_к_точке монтирования_бэкапа/backup/db_860592284_122.bk tag=FULL_DB
channel ORA_AUX_DISK_1: restore complete, elapsed time: 00:00:01
archive log filename=/data/TEST/flash_recovery_area/TEST/archivelog/2014_10_10/o1_mf_1_3304_b3h993g7_.arc thread=1 sequence=3304
channel clone_default: deleting archive log(s)
archive log filename=/data/TEST/flash_recovery_area/TEST/archivelog/2014_10_10/o1_mf_1_3304_b3h993g7_.arc recid=1 stamp=860599299
media recovery complete, elapsed time: 00:00:01
Finished recover at 10-OCT-14

contents of Memory Script:
{
shutdown clone;
startup clone nomount ;
}
executing Memory Script

database dismounted
Oracle instance shut down

connected to auxiliary database (not started)
Oracle instance started

Total System Global Area 1610612736 bytes

Fixed Size 2084296 bytes
Variable Size 385876536 bytes
Database Buffers 1207959552 bytes
Redo Buffers 14692352 bytes
sql statement: CREATE CONTROLFILE REUSE SET DATABASE "TEST" RESETLOGS ARCHIVELOG
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 100
MAXINSTANCES 8
MAXLOGHISTORY 584
LOGFILE
GROUP 1 ( '/data/TEST/redo01.log' ) SIZE 50 M REUSE,
GROUP 2 ( '/data/TEST/redo02.log' ) SIZE 50 M REUSE,
GROUP 3 ( '/data/TEST/redo03.log' ) SIZE 50 M REUSE
DATAFILE
'/data/TEST/system01.dbf'
CHARACTER SET CL8MSWIN1251


contents of Memory Script:
{
set newname for tempfile 1 to
"/data/TEST/temp01.dbf";
switch clone tempfile all;
catalog clone datafilecopy "/data/TEST/undotbs01.dbf";
catalog clone datafilecopy "/data/TEST/sysaux01.dbf";
catalog clone datafilecopy "/data/TEST/users01.dbf";
switch clone datafile all;
}
executing Memory Script

executing command: SET NEWNAME

renamed temporary file 1 to /data/TEST/temp01.dbf in control file

cataloged datafile copy
datafile copy filename=/data/TEST/undotbs01.dbf recid=1 stamp=860599305

cataloged datafile copy
datafile copy filename=/data/TEST/sysaux01.dbf recid=2 stamp=860599305

cataloged datafile copy
datafile copy filename=/data/TEST/users01.dbf recid=3 stamp=860599305

datafile 2 switched to datafile copy
input datafile copy recid=1 stamp=860599305 filename=/data/TEST/undotbs01.dbf
datafile 3 switched to datafile copy
input datafile copy recid=2 stamp=860599305 filename=/data/TEST/sysaux01.dbf
datafile 4 switched to datafile copy
input datafile copy recid=3 stamp=860599305 filename=/data/TEST/users01.dbf

contents of Memory Script:
{
Alter clone database open resetlogs;
}
executing Memory Script

database opened
Finished Duplicate Db at 10-OCT-14

RMAN>

Вкратце последовательность действий:

  1. Запускаем целевой инстанс в режиме NOMOUNT.
  2. Создаем из написанного нами init.ora spfile.
  3. Соединяемся из RMAN с продуктивной базой (бэкап уже физически перенесен на целевую систему!)
  4. Выполняем клонирование.
В нашем примере продуктивная база условно названа PROD, клон - TEST. Замените имена на ваши. :) Точка монтирования клонируемой базы - /data/TEST, то есть отличающаяся от продуктивной системы.

После клонирования скорректируйте файл параметров базы-клона по необходимости.

"Реконструкция завершена" (с) "Пятый элемент" :)