В некоторых информационных системах требуется обеспечить бесперебойный доступ
к БД невзирая на всевозможные сбои и отказы оборудования и программ. Задача
придать системе "высокую степень доступности" не имеет единственного
решения в ИТ, а вместо этого имеет гамму разных решений, каждое со своими выгодами
и ограничениями. Многие из таких решений реализованы и в Oracle рядом специальных
конфигураций системы СУБД-БД. Одно из самых доступных - организация "горячего
резерва". В Oracle для обозначения горячего резерва используется термин
"standby".
Основные принципы горячего резервирования
В общем, принципы организации горячего резерва в Oracle довольно просты:
(1) Организуются две активные БД: одна основная, и другая резервная.
(2) Основная БД работает в режиме архивирования журналов. На возможность подсоединения
к ней и на работу с данными никаких ограничений не накладывается.
(3) Резервная БД работает в специальном режиме постоянного восстановления с
архивированных журналов, получаемых от основной БД; она все время "догоняет"
основную.
(4) Из этого специального режима резервную БД можно перевести в другой, когда
она приостановит процедуру восстановления и сможет предоставить свои данные,
однако только для чтения. Из этого второго режима мы может вернуться в первый,
для нее основной.
(5) Кроме этого, из режима восстановления резервную БД можно перевести в режим
обычной полнофункциональной БД, но теперь уже безвозвратно.
Техника "standby" существует в Oracle давно, и в деталях реализации
претерпела за прошедшее время несколько изменений. Ниже она будет описана по
состоянию для версии 9.0.
Что дает пример ниже
Техника горячего резервирования описана в документации по Oracle. Однако давно
замечено (интересно, что и в фирме об этом знают!), что эта документация, за
исключением избранных мест, не может служить толковым учебником. К горячему
резервированию это относится в полной мере.
С другой стороны есть целый ряд статей, где методично рассказано, как организовать
standby database. Однако они все или относятся к Unix, и/или содержат ошибки
- по крайней мере те, что попадались мне на глаза.
Пример организации резервного копирования ниже
а) относится к платформе Windows, то есть наиболее демократичен в смысле аудитории
б) не требует наличия второй машины (что, в общем, бестолково для реальной практики,
но вполне нормально, и даже удобно, для знакомства)
в) не содержит ошибок.
Пользователи на платформе Unix, как правило, более продвинутые, без особого
труда внесут в приводимый пример необходимые правки.
Постановка задачи и план решения
Пусть имеется БД teacher.class (использовано глобальное именование БД). Создадим
для нее резервную БД с именем sb.class (имя sb часто используется в таких примерах,
но это - чистая условность). Она будет работать на той же машине, что и teacher.class.
Расположения каталогов будем считать OFA-удовлетворительным.
Для teacher.class должна иметься копия БД (проще, если холодная) и должен быть
включен режим архивации. Если этого нет, перед выполнением примера нужно об
этом позаботиться.
Вот, для определенности, выдержка из файла INIT.ORA для teacher.class в исходном
состоянии:
background_dump_dest=d:\oracle\admin\teacher\bdump
core_dump_dest=d:\oracle\admin\teacher\cdump
user_dump_dest=d:\oracle\admin\teacher\udump
db_domain="class"
global_names = true
remote_login_passwordfile=EXCLUSIVE
compatible=9.0.0
db_name=teacher
instance_name=teacher
##################################
log_archive_start = true
log_archive_dest = "e:\oracle\oradata\teacher\archive"
log_archive_format = teachers%s.arc
|
План нижеприводимого решения включает следующие действия:
- Подготовка основной БД к работе в спарке с резервной
- Клонирование основной БД и формирование из полученного клона резервной
БД
- Конфигурирование сетевых компонент Oracle Net для возможности общения двух
БД друг с другом
- Запуск резервной БД в рабочем режиме
Подготовка места для резервной БД
Сначала резервная БД создается клонированием основной, затем мы "вдохнем
в нее жизнь" и запустим в режиме восстановления. Поэтому прежде всего для
sb.class нужно подготовить место на диске.
В нашем примере это каталог d:\oracle\admin\sb с подкаталогами udump, bdump,
cdump и pfile, а также c:\oracle\oradata\sb - их нужно завести.
Еще не забудем завести каталог e:\oracle\oradata\sb\archive для хранения собственных
архивов sb.class (на будущее, когда эту базу переведут в основной режим) и каталог
e:\oracle\oradata\sb\teacher_archive для приема архивов от teacher.class.
Готовим основную БД
Подправим INIT.ORA для teacher.class:
background_dump_dest=d:\oracle\admin\teacher\bdump
core_dump_dest=d:\oracle\admin\teacher\cdump
user_dump_dest=d:\oracle\admin\teacher\udump
db_domain="class"
global_names = true
remote_login_passwordfile=EXCLUSIVE
control_files=("c:\oracle\oradata\teacher\control01.ctl")
compatible=9.0.0
db_name=teacher
instance_name=teacher
##################################
log_archive_start = true
#####log_archive_dest = "e:\oracle\oradata\teacher\archive"
log_archive_dest_1 = "location=e:\oracle\oradata\teacher\archive"
log_archive_format = teachers%s.arc
log_archive_dest_state_1 = enable
log_archive_dest_2 = "service=sb.class"
log_archive_dest_state_2 = enable
log_archive_min_succeed_dest = 1
fal_client = "sb.class"
|
Правкой затронута только нижняя часть, отделенная строкой из #.
Во-первых, от параметра LOG_ARCHIVE_DEST (сохраненному для совместимости) мы
перешли к более современному LOG_ARCHIVE_DEST_1. Параметры LOG_ARCHIVE_DEST_N
в последних версиях Oracle задают направления копирования освободившихся журналов
в архив, а параметры LOG_ARCHIVE_DEST_STATE_N позволяют имеющиеся направления
"включать" и временно "отключать".
В нашем случае к старому архиву e:\oracle\oradata\teacher\archive добавилось
как раз еще одно такое направление, но уже не в виде каталога, как раньше, а
в виде БД, которой teacher.class будет пересылать свои журналы.
Параметр FAL_CLIENT = "sb.class" уточняет, что это будет резервная
БД sb.class и что пересылка будет автоматической.
Остановим основную БД и выдадим в SQL*Plus:
STARTUP PFILE=?/database/initteacher.ora
ALTER DATABASE CREATE STANDBY CONTROLFILE AS 'c:\oracle\oradata\sb\control01.ctl';
ALTER SYSTEM ARCHIVE LOG CURRENT;
SHUTDOWN
То есть мы приготовили контрольный файл для резервной БД и зафиксировали точку
отсчета для пересылки архивируемых журналов на sb.class.
Готовим клон для резервной БД
Копируем все файлы БД teacher.class, кроме контрольного, в c:\oracle\oradata\sb.
Контрольный там уже есть.
Копируем INIT.ORA БД teacher.class в d:\oracle\admin\teacher\pfile. Правим
его:
background_dump_dest=d:\oracle\admin\sb\bdump
core_dump_dest=d:\oracle\admin\sb\cdump
user_dump_dest=d:\oracle\admin\sb\udump
db_domain="class"
global_names = true
remote_login_passwordfile=EXCLUSIVE
control_files=("c:\oracle\oradata\sb\control01.ctl")
compatible=9.0.0
db_name=teacher
instance_name=sb
##################################
log_archive_format = teachers%s.arc
db_file_name_convert = "\ORADATA\TEACHER", "\ORADATA\SB"
log_file_name_convert = "\ORADATA\TEACHER", "\ORADATA\SB"
standby_archive_dest = "e:\oracle\oradata\sb\teacher_archive"
log_archive_dest = "e:\oracle\oradata\sb\archive"
lock_name_space = sb
fal_server = "teacher.class"
|
Обратите внимание на изменение имен каталогов и названий в верхней части текста,
однако главные изменения расположены ниже строки-комментария.
Параметры DB_FILE_NAME_CONVERT и LOG_FILE_NAME_CONVERT нужны только если структуры
каталогов основной и резервной БД не совпадают. В нашем случае, когда обе БД
работают на одной машине, это неизбежно. Когда обе БД работают на разных машинах,
проще использовать одинаковую структуру каталогов и об этих параметрах забыть.
Параметр STANDBY_ARCHIVE_DEST указывает на каталог, куда "принимающая
сторона" sb.class будет складывать поступающие от teacher.class архивные
копии журнала.
Параметр LOG_ARCHIVE_DEST задает каталог-архив уже для своих изменений sb.class
(на будущее).
Параметр LOCK_NAME_SPACE нужен только в нашей не типичной для практики ситуации,
когда обе БД будут работать на одной машине; без него две СУБД не смогут одновременно
общаться с разными БД, имеющими одинаковые имена.
Наконец, параметр FAL_SERVER симметричен FAL_CLIENT в INIT-файле для teacher.class.
Копируем из e:\oracle\oradata\teacher\archive в e:\oracle\oradata\sb\teacher_archive
последний по времени архивированный файл.
Обеспечиваем взаимодействие по Oracle Net
Нужно ненадолго отвлечься от резервной БД и подправить файлы listener.ora и
tnsnames.ora, чтобы обе СУБД могли общаться. У нас будет автоматическая пересылка
файлов на резервную БД (а могли бы этого не делать и переносить архивные файлы
вручную, но это не очень интересно), и для этого основная база должна уметь
соединяться с резервной. Нужные конфигурационные файлы у нас находятся в одном
месте: в %oracle_home%\network\admin, а в "боевых условиях" они будут
разнесены по разным машинам. Добавляем в listener.ora фрагмент:
(SID_LIST =
(оставить, как было)
(SID_DESC =
(GLOBAL_DBNAME = teacher.class)
(ORACLE_HOME = c:\oracle\ora90)
(SID_NAME = sb)
)
)
|
После этого listener надо перезапустить, проще всего - через окошко Services
в ОС Windows, но можно и из командной строки.
В файл tnsnames.ora добавляем
sb.class =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST
= wsa46)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = sb)
)
)
|
"Оживляем" резервную БД и запускаем ее
Теперь резервную БД нужно "оживить". Войдем в консольном окошке ОС
в каталог %oracle_home%\database. Скопируем initteacher.ora в initsb.ora и подправим
в initsb.ora ссылку на файл: IFILE='c:\oracle\admin\teacher\pfile\init.ora'
заменим на IFILE='c:\oracle\admin\sb\pfile\init.ora'.
Создадим файл пароля для sb.class:
orapwd file=PWDsb.ora password=change_on_install
Заведем службу ОС для sb.class:
oradim -new -sid sb -startmode m -pfile c:\oracle\ora90\database\initsb.ora
"Приводим" резервную БД "в чувство" и переводим в режим
автоматического подката по получаемым файлам журналов. Выдаем в SQL*Plus:
CONNECT sys/change_on_install AS SYSDBA
STARTUP MOUNT PFILE=?/database/initsb.ora
RECOVER MANAGED STANDBY DATABASE
В этом месте SQL*Plus "зависает", но так и должно быть. Уходим из
этого окошка, но не закрываем его.
Проверка
Теперь можно для наглядности вывести на экран два окошка с содержимым каталогов
e:\oracle\oradata\teacher\archive и e:\oracle\oradata\sb\teacher_archive соответственно.
Запускаем снова основную БД в окошке с SQL*Plus, где мы эту базу останавливали:
STARTUP PFILE=?/database/initteacher.ora
Выдадим несколько раз
ALTER SYSTEM SWITCH LOGFILE;
Если все было проделано без ошибок, в обоих окошках с каталогами можно наблюдать
появление одних и тех же архивных копий журнала, причем с запаздыванием: сначала
в одном, потом в другом. Это свидетельствует о том, что архивные копии реально
пересылаются на резервную БД.
Еще для проверки можно запустить и процесс внесения в основную БД фактических
изменений, в результате чего журнальные файлы начнут переключаться самостоятельно.
Для нас результат должен быть тем же самым.
Перевод резервной БД в состояние, допускающее выборку
Откроем новое консольное окошко, где выдадим в SQL*Plus:
CONNECT sys/change_on_install@sb.class AS SYSDBA
RECOVER MANAGED STANDBY CANCEL
EXIT
Вернемся в прежнее окошко с резервной БД и увидим, что сеанс SQL*Plus в нем
"отвис". Сейчас архивные копии продолжают поступать в резервную БД,
однако сама база уже не подкатывается. Наберем
ALTER DATABASE OPEN READONLY;
Теперь из резервной базы можно делать выборки данных.
Возврат резервной БД в режим подката
В этом же последнем окошке набираем:
CONNECT sys/change_on_install AS SYSDBA
SHUTDOWN
STARTUP MOUNT PFILE=?/database/initsb.ora
RECOVER AUTOMATIC STANDBY DATABASE
CANCEL
RECOVER MANAGED STANDBY DATABASE
Как и прежде, тут мы "зависаем".
Перевод резервной БД в рабочее состояние
Вначале поступаем, как и прежде, а потом - иначе. В новом окошке выдадим в
SQL*Plus:
CONNECT sys/change_on_install@sb.class AS SYSDBA
RECOVER MANAGED STANDBY CANCEL
ALTER DATABASE RECOVER STANDBY DATABASE;
ALTER DATABASE RECOVER CANCEL;
ALTER DATABASE ACTIVATE STANDBY DATABASE;
Теперь правильнее всего будет остановить бывшую резервную, а отныне - рабочую
БД, снять с нее холодную копию, проделать необходимые правки в файлах Oracle
Net и запустить базу снова и подготовить для нее новый резерв. После этого можно
будет использовать ее в рабочем режиме.