12июн
Создание горячей резервной базы данных (standby). Заметки по собственному опыту.
Если Вы уверены, что Вам нужно организовать горячее резервирование, и Вы знаете что такое STANDBY только теоретически, то данная статья станет Вам хорошим подспорьем в получении первоначальных практических навыков. Теоретические аспекты тут не освещаются, а изложен пошагово весь процесс создания резервной базы данных. Основные этапы:
Начнем с того, что на двух физически разных компьютерах есть базы данных ORACLE:
На резервном сервере my_host создана база данных my_db.world.
Tnsnames.ora
my_st_db.world=
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = my_host)(PORT = 1521)) )
(CONNECT_DATA =
(SERVICE_NAME = my_db.world) ) )
На основном сервере есть база данных my_db.world.
Tnsnames.ora
MY_DB.WORLD =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = primary_host)(PORT = 1521)) )
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = my_db.world) ) )
Алиас резервного сервера нужно добавить в tnsnames.ora на основном сервере и наоборот.
На основной базе PRIMARY
шаг 1 Чтобы получить полный список файлов, которые будем копировать на резервный сервер, выполним
следующие команды:
SELECT NAME FROM V$DATAFILE;
select member from v$logfile;
шаг 2 получим init.ora :
create pfile from spfile
шаг 3 подправляем полученный initmy_db.ora
log_archive_dest_2 = "service=my_st_db.world"
log_archive_dest_state_2 = enable
log_archive_min_succeed_dest = 1
fal_client = " service=my_st_db.world"
log_archive_format= ARC%S.%T
log_archive_start=TRUE
шаг 4
SQL> ALTER SYSTEM ARCHIVE LOG CURRENT;
System altered.
шаг 5
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
шаг 6 Копируем файлы данных, оперативные файлы журнализации (redo logs) и файл паролей PWDmy_db.ora в соответствующие папки на сервере, где будет standby. Архивные файлы журнализации не переносим.
шаг 7 После чего основной сервер поднимаем таким образом:
SQL> startup pfile=C:\oracle\ora92\database\initmy_db.ora;
ORACLE instance started.
Total System Global Area 2677617140 bytes
Fixed Size 459252 bytes
Variable Size 1728053248 bytes
Database Buffers 947912704 bytes
Redo Buffers 1191936 bytes
Database mounted.
Database opened.
шаг 8 Создаем управляющий файл для резервной базы данных:
SQL> ALTER DATABASE CREATE STANDBY CONTROLFILE AS 'k:\oracle\oradata\control01.ctl';
Database altered.
шаг 9 Перенесем на резервный сервер этот файл и сделаем еще две копии.
На резервном сервере Standby
шаг 1 создаем init.ora
SQL> create pfile from spfile;
File created.
шаг 2
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
шаг 3 Корректируем init.ora:
Меняем расположение control файлов если нужно
Добавляем
db_file_name_convert = "k:\oracle\ORADATA\my_db", "c:\oracle\ORADATA\my_db "
log_file_name_convert = "k:\oracle\ORADATA\my_db", "c:\oracle\ORADATA\my_db "
эти две строчки нужны, если у наших баз данных файлы данных размещаются на разных дисках
standby_archive_dest = "c:\oracle\oradata\my_db\my_db_archive"
log_archive_dest_1='LOCATION= c:\oracle\oradata\my_db\my_db_archive'
log_archive_dest_state_1=enable
fal_server = "my_db.world"
log_archive_format= ARC%S.%T
log_archive_start=true
standby_file_management=AUTO
remote_archive_enable=TRUE
шаг 4 Вносим изменения в listener.ora:
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = my_host)(PORT = 1521))
)
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0)))))
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = C:\oracle\ora92)
(PROGRAM = extproc)
)
(SID_DESC =
(GLOBAL_DBNAME = my_st_db.world)
(ORACLE_HOME = C:\oracle\ora92)
(SID_NAME = my_db))
(SID_DESC =
(GLOBAL_DBNAME = my_db.world)
(ORACLE_HOME = C:\oracle\ora92)
(SID_NAME = my_db)) )
шаг 5 Уничтожение мертвых соединений на Standby сервере нужно активировать путем установки параметра SQLNET.EXPIRE_TIME в значение 2 (вообще Вам решать какое время здесь выставить) в файле SQLNET.ORA
SQLNET.EXPIRE_TIME=2
шаг 6
SQL> STARTUP NOMOUNT PFILE=C:\oracle\ora92\database\initmy_db.ora;
ORACLE instance started.
Total System Global Area 1058087636 bytes
Fixed Size 455380 bytes
Variable Size 109051904 bytes
Database Buffers 947912704 bytes
Redo Buffers 667648 bytes
шаг 7
SQL> alter database mount standby database;
Database altered.
шаг 8
SQL> alter database recover managed standby database;
Зависает (идет процесс наката архивных файлов). Это хорошо видно в alert.log :
alter database recover managed standby database
Media Recovery Start: Managed Standby Recovery
Starting datafile 1 recovery in thread 1 sequence 96
Datafile 1: 'C:\ORACLE\ORADATA\MY_DB\SYSTEM01.DBF'
Starting datafile 2 recovery in thread 1 sequence 96
Datafile 2: 'C:\ORACLE\ORADATA\MY_DB\UNDOTBS01.DBF'
Starting datafile 3 recovery in thread 1 sequence 96
Datafile 3: 'C:\ORACLE\ORADATA\MY_DB\CWMLITE01.DBF'
Starting datafile 4 recovery in thread 1 sequence 96
Datafile 4: 'C:\ORACLE\ORADATA\MY_DB\DRSYS01.DBF'
Starting datafile 5 recovery in thread 1 sequence 96
Datafile 5: 'C:\ORACLE\ORADATA\MY_DB\EXAMPLE01.DBF'
Starting datafile 6 recovery in thread 1 sequence 96
Datafile 6: 'C:\ORACLE\ORADATA\MY_DB\INDX01.DBF'
Starting datafile 7 recovery in thread 1 sequence 96
Datafile 7: 'C:\ORACLE\ORADATA\MY_DB\ODM01.DBF'
Starting datafile 8 recovery in thread 1 sequence 96
Datafile 8: 'C:\ORACLE\ORADATA\MY_DB\TOOLS01.DBF'
Starting datafile 9 recovery in thread 1 sequence 96
Datafile 9: 'C:\ORACLE\ORADATA\MY_DB\USERS01.DBF'
Starting datafile 10 recovery in thread 1 sequence 96
Datafile 10: 'C:\ORACLE\ORADATA\MY_DB\XDB01.DBF'
Media Recovery Log
Media Recovery Waiting for thread 1 seq# 96
После чего настает зависание - ожидание архивного файла.
шаг 9 Удобно вместо команды alter database recover managed standby database; Использовать команду
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
В этом случае восстановлением не будет заниматься серверный процесс (текущаяя сессия), накат архивных файлов будет проводиться фоновым процессом MRP.
Тест работы нашей связки серверов.
На основном сервере
- переключим журналы alter system switch logfile;
- появился новый архивный файл
- скопировался автоматически на резервный сервер
Это все видно в алерте:
Mon Apr 02 15:57:39 2007
ARC1: Evaluating archive log 1 thread 1 sequence 97
Mon Apr 02 15:57:39 2007
ARC1: Beginning to archive log 1 thread 1 sequence 97
Creating archive destination LOG_ARCHIVE_DEST_2: 'my_st_db.world'
Creating archive destination LOG_ARCHIVE_DEST_1: 'K:\ORACLE\ORADATA\MY_DB\ARCHIVE\ARC00097.001'
ARC1: Completed archiving log 1 thread 1 sequence 97
На резервном сервере
Media Recovery Log C:\ORACLE\ORADATA\MY_DB\MY_DB_ARCHIVE\ARC00097.001
Media Recovery Waiting for thread 1 seq# 98
- и сервер завис в ожидании следующего архива.
-
Прекращение наката на резервном сервере.
Открываем другой sqlplus и прекращаем накат:
SQL> conn sys/primary_host@my_st_db.world as sysdba
Connected.
SQL> recover managed standby database cancel;
Media recovery complete.
В первом окне sqlplus появляется
SQL> alter database recover managed standby database;
alter database recover managed standby database
*
ERROR at line 1:
ORA-16043: managed recovery session canceled
ORA-16037: user requested cancel of managed recovery operation
В alert.log появляются сообщения
ALTER DATABASE RECOVER managed standby database cancel
Media Recovery user canceled with status 16037
ORA-16043 signalled during: ALTER DATABASE RECOVER managed standby database ...
Managed Standby Recovery Cancelled
Completed: ALTER DATABASE RECOVER managed standby database cancel
Перевод резервной базы данных в режим «Только чтение»
После остановки наката базу можно перевести в режим чтения.
После выполнения команды
ALTER DATABASE OPEN READ ONLY;
база откроется для чтения. Позже можно вернуться в состояние наката.
Перевод базы данных в режим «Чтение-запись».
Для того чтобы резервная база данных стала промышленной, нужно
Но вернуть ее в состояние standby уже будет невозможно.
- выполним
RECOVER MANAGED STANDBY DATABASE FINISH
В алерте получаем сообщения:
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE FINISH
Thu Apr 12 12:22:45 2007
Terminal Recovery: request posted
Thu Apr 12 12:22:54 2007
There are no standby current logs; terminal recovery is not required.
MRP0: Background Media Recovery user canceled with status 16137
MRP0: Background Media Recovery process shutdown
Thu Apr 12 12:22:56 2007
Terminal Recovery: completion detected
Completed: ALTER DATABASE RECOVER MANAGED STANDBY DATABASE
На данном этапе у вас еще есть возможность вернуться к standby! Просто нужно ввести команду ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;
- теперь
ALTER DATABASE ACTIVATE STANDBY DATABASE;
В алерте получаем сообщения:
Thu Apr 12 12:32:24 2007
ALTER DATABASE ACTIVATE STANDBY DATABASE
Thu Apr 12 12:32:24 2007
ALTER DATABASE ACTIVATE [PHYSICAL] STANDBY DATABASE
RESETLOGS after incomplete recovery UNTIL CHANGE 26622215
Resetting resetlogs activation ID 1600857482 (0x5f6b258a)
Thu Apr 12 12:32:40 2007
Activation complete - Database shutdown not required
Completed: ALTER DATABASE ACTIVATE STANDBY DATABASE
- для временного табличного пространства
CREATE TEMPORARY TABLESPACE TEMP TEMPFILE 'C:\oracle\oradata\my_db\temp01.dbf' SIZE 100M;
или
ALTER TABLESPACE TEMP ADD TEMPFILE 'C:\oracle\oradata\my_db\temp01.dbf' REUSE;
После этого произойдет 'open resetlogs'. Базу надо остановить, сделать полный холодный бэкап, подправить init.ora и стартовать теперь уже промышленную базу данных.
Database Switchover (Переключение Primary <-> Standby и обратно)
Одна из полезных возможностей предоставляемых standby это временно переключиться на standby DB и потом вернуться на primary DB.
База данных может быть в одном из двух взаимно исключающих режимах (первичный или резервный). Но базы данных могут одновременно поменяться этими ролями без потери данных, не выполняя переключения redo logs. Этот процесс известный как Switchover и может быть выполнен, используя следующие команды:
Переключение основной базы в резервную (primary database -> standby)
Указать параметр инициализации standby_archive_dest
Выполнить команды:
ALTER SYSTEM ARCHIVE LOG CURRENT;
alter system set log_archive_dest_state_2=defer scope=both;
Остановить все программные продукты, которые работают с основной базой.
Теперь выполнить:
alter system set job_queue_processes = 0;
alter system set aq_tm_processes = 0;
alter database commit to switchover to physical standby;
или
alter database commit to switchover to PHYSICAL STANDBY WITH SESSION SHUTDOWN;
SHUTDOWN IMMEDIATE;
STARTUP NOMOUNT PFILE=init.ora
ALTER DATABASE MOUNT STANDBY DATABASE;
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE;
Теперь основная база данных работает как резервная (standby)
Переключение резервной базы данных в основную (standby database -> primary).
На резервном сервере завершить накат всех логов.
Указать параметр инициализации log_archive_dest_2 = "service=алиас_нового_резервного_сервера"
Выполнить команды:
ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY;
SHUTDOWN IMMEDIATE;
STARTUP PFILE=\init.ora
alter system set log_archive_dest_state_2=ENABLE SCOPE=BOTH;
Теперь бывшая резервная база данных работает как основная.
Процесс обратного преобразования называется Switchback, то есть выполнение еще одного switchover но в обратном направлении.
Задержка применения redo информации на standby базе данных

Если на резервной базе данных произошла потеря данных (аппаратная, пользовательская), то весьма полезно отложить на определенное время накат redo информации на резервной базе данных. Это можно реализовать командой :
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DELAY 30;
Так устанавливается накат автоматический накат с опозданием на 30 минут.
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE NODELAY;
Несколько замечаний
Ошибки, возникшие в процессе работы
На резервном сервере (standby) не появлялись архивные файлы (основной сервер их автоматически не поставлял). На основном сервере (primary) в алерте выдавало такие сообщения:
Completed: ALTER DATABASE OPEN
Fri Mar 30 15:52:27 2007
Thread 1 advanced to log sequence 84
Current log# 3 seq# 84 mem# 0: K:\ORACLE\ORADATA\MY_DB\REDO03.LOG
Current log# 3 seq# 84 mem# 1: K:\ORACLE\ORADATA\MY_DB\REDO03_1.LOG
Current log# 3 seq# 84 mem# 2: K:\ORACLE\ORADATA\MY_DB\REDO03_2.LOG
Fri Mar 30 15:52:27 2007
ARC0: Evaluating archive log 2 thread 1 sequence 83
ARC0: Beginning to archive log 2 thread 1 sequence 83
Creating archive destination LOG_ARCHIVE_DEST_2: 'my_st_db.world'
Fri Mar 30 15:52:27 2007
Errors in file c:\oracle\admin\my_db\bdump\my_db_arc1_2624.trc:
ORA-16032: parameter destination string cannot be translated
ARC0: Error 16032 Creating archive log file to 'my_st_db.world'
Fri Mar 30 15:52:27 2007
Errors in file c:\oracle\admin\my_db\bdump\my_db_arc0_3892.trc:
ORA-16032: parameter destination string cannot be translated
Creating archive destination LOG_ARCHIVE_DEST_1: 'K:\ORACLE\ORADATA\MY_DB\ARCHIVE\ARC00083.001'
ARC0: Completed archiving log 2 thread 1 sequence 83
Fri Mar 30 15:58:10 2007
Errors in file c:\oracle\admin\my_db\bdump\my_db_arc0_3892.trc:
ORA-16032: parameter destination string cannot be translated
А в файле трассировки:
*** SESSION ID:(9.1) 2007-03-30 15:52:27.000
Standby parameter STANDBY_ARCHIVE_DEST string is invalid at host 'my_st_db.world'
Error 16032 attaching to destination LOG_ARCHIVE_DEST_2 standby host 'my_st_db.world'
*** 2007-03-30 15:52:27.000
ARC0: Error 16032 Creating archive log file to 'my_st_db.world'
*** 2007-03-30 15:52:27.000
kcrrfail: dest:2 err:16032 force:0
ORA-16032: parameter destination string cannot be translated
- Created archivelog as 'K:\ORACLE\ORADATA\MY_DB\ARCHIVE\ARC00083.001'
*** 2007-03-30 15:58:10.000
Standby parameter STANDBY_ARCHIVE_DEST string is invalid at host 'my_st_db.world'
Error 16032 attaching to destination LOG_ARCHIVE_DEST_2 standby host 'my_st_db.world'
Heartbeat failed to connect to standby 'my_st_db.world'. Error is 16032.
*** 2007-03-30 15:58:10.000
kcrrfail: dest:2 err:16032 force:0
ORA-16032: parameter destination string cannot be translated
*** 2007-03-30 16:03:17.000
Error 1089 attaching RFS server to standby instance at host 'my_st_db.world'
Error 1089 attaching to destination LOG_ARCHIVE_DEST_2 standby host 'my_st_db.world'
Heartbeat failed to connect to standby 'my_st_db.world'. Error is 1089.
Все настройки на основном сервере были правильные, несколько раз проверенные.
Но ларчик открывался просто, но не на основном сервере.
На резервном сервере в init.ora был неверно выставлен параметр standby_archive_dest (ошибка в названии папки). Но интересное наступило потом. После монтирования резервной базы, основная база «почувствовала» исправления и автоматически перекинула все архивные файлы на резервный сервер. На основном сервере в алерте появились такие сообщения:
ARC1: Beginning to archive log 3 thread 1 sequence 84
Creating archive destination LOG_ARCHIVE_DEST_2: 'my_st_db.world'
Creating archive destination LOG_ARCHIVE_DEST_1: 'K:\ORACLE\ORADATA\MY_DB\ARCHIVE\ARC00084.001'
ARC1: Completed archiving log 3 thread 1 sequence 84
Fri Mar 30 16:06:50 2007
Current log# 4 seq# 85 mem# 0: K:\ORACLE\ORADATA\MY_DB\REDO04.LOG
Fri Mar 30 16:06:50 2007
Current log# 4 seq# 85 mem# 1: K:\ORACLE\ORADATA\MY_DB\REDO04_1.LOG
Current log# 4 seq# 85 mem# 2: K:\ORACLE\ORADATA\MY_DB\REDO04_2.LOG
Fri Mar 30 16:06:50 2007
ARC1: Begin FAL archive (thread 1 sequence 70 destination my_st_db.world)
Fri Mar 30 16:06:50 2007
ARC0: Begin FAL archive (thread 1 sequence 69 destination my_st_db.world)
Creating archive destination LOG_ARCHIVE_DEST_2: 'my_st_db.world'
Fri Mar 30 16:06:50 2007
Creating archive destination LOG_ARCHIVE_DEST_2: 'my_st_db.world'
ARC0: Complete FAL archive (thread 1 sequence 69 destination my_st_db.world)
Fri Mar 30 16:06:50 2007
ARC1: Complete FAL archive (thread 1 sequence 70 destination my_st_db.world)
Fri Mar 30 16:06:50 2007
ARC0: Begin FAL archive (thread 1 sequence 71 destination my_st_db.world)
Fri Mar 30 16:06:50 2007
Creating archive destination LOG_ARCHIVE_DEST_2: 'my_st_db.world'
Fri Mar 30 16:06:51 2007
ARC1: Begin FAL archive (thread 1 sequence 72 destination my_st_db.world)
ARC0: Complete FAL archive (thread 1 sequence 71 destination my_st_db.world)
Fri Mar 30 16:06:51 2007
Creating archive destination LOG_ARCHIVE_DEST_2: 'my_st_db.world'
Fri Mar 30 16:06:51 2007
ARC0: Begin FAL archive (thread 1 sequence 73 destination my_st_db.world)
Creating archive destination LOG_ARCHIVE_DEST_2: 'my_st_db.world'
Fri Mar 30 16:06:52 2007
ARC1: Complete FAL archive (thread 1 sequence 72 destination my_st_db.world)
ARC1: Begin FAL archive (thread 1 sequence 74 destination my_st_db.world)
Fri Mar 30 16:06:52 2007
ARC0: Complete FAL archive (thread 1 sequence 73 destination my_st_db.world)
Fri Mar 30 16:06:52 2007
Creating archive destination LOG_ARCHIVE_DEST_2: 'my_st_db.world'
Fri Mar 30 16:06:52 2007
И так далее
УРА ORACLE!
Вывод:
основная база данных, после монтирования резервной базы, автоматически ей поставляет архивные файлы журнализации, начиная с первого непереданного и заканчивая последним созданным. Даже если вы архивные файлы сначала переместили ( например, удалили после холодного бэкапа), а затем восстановили на прежнее место, то файлы все равно попадут на резервный сервер.
Немного из документации.
Уничтожение “мертвых” соединений
Если установленное пользователем соединение с Oracle прерывается (например, на рабочей станции выключили питание), когда сеанс не активен, то есть Oracle ждет от рабочей станции оператора для выполнения, то серверный процесс, работающий с этим соединением, может ждать вечно. Это может создавать проблемы при эксплуатации. Поэтому в Oracle предусмотрен механизм для выявления таких соединений и удаления ожидающего серверного процесса. Для этого в файле sqlnet.ora нужно задать строку:
sqlnet.expire_time = n
где n – интервал между проверками в минутах.
По завершении интервала Oracle посылает по всем соединениям пустые пакеты, игнорируемые работающими клиентами. Если же физического соединения нет, то приходит ошибка “delivery error” и данный серверный процесс уничтожается с откатом всех его транзакций. Задание слишком маленького интервала захламляет сеть излишними пакетами. Слишком большой интервал может блокировать пользователей, обновляющих запись, замкнутую “мертвой” транзакцией.

Пример, LOG_ARCHIVE_DEST_2='SERVICE=stby1 LGWR SYNC AFFIRM'
Немного из документации о параметре инициализации LOG_ARCHIVE_DEST_STATE
For every LOG_ARCHIVE_DEST_n initialization parameter that you define, specify a corresponding LOG_ARCHIVE_DEST_STATE_n parameter. The LOG_ARCHIVE_DEST_STATE_n (where n is an integer from 1 to 10) initialization parameter specifies whether the corresponding destination is currently on (enabled) or off (disabled). Table 5-1 describes the LOG_ARCHIVE_DEST_STATE_n parameter attributes.
ENABLE Redo transport services can transmit redo data to this destination. This is the default.
DEFER Redo transport services will not transmit redo data to this destination. This is a valid but unused destination.
ALTERNATE This destination is not enabled, but it will become enabled if communication to its associated destination fails.
RESET Functions the same as DEFER, but clears any error messages for the destination if it had previousl
Документацию смотри здесь.