2011-04-29

Борьба с ошибкой ORA-12560

При подключении sqlplus / as sysdba или с использованием listener sqlplus sys/syspassword@db возникает ошибка:
ORA-12560: TNS:ошибка адаптера протокола

Все шаги в совокупности дали желаемый результат.

1. Проверяем переменную ORACLE_SID (устанавливается или в переменных окружения или в реестре). Если переменная не установлена или установлена не правильно, этот шаг поможет при подключении без листенера sqlplus / as sysdba.

После исправления первого шага, возможно возникновение ошибки:
ORA-01031: insufficient privileges
Самая распространенная причина этого: необходимо прописать SQLNET.AUTHENTICATION_SERVICES = (NTS) в файле sqlnet.ora на сервере.

2. Для подключений через listener
Проверить, что в listener.ora прописаны правильные настройки. У меня все падало из-за неправильно выставленного
(SID_NAME=...)

После исправления и перезапуска все начало нормально подключаться

2011-04-23

Проблемы с Enterprise manager

На тестовой базе возникли проблемы с EM (хотя не посредстенно после создания базы он работал):

Enterprise Manager is not able to connect to the database instance. The state of the components are listed below.

Предлагаемые в итернете решения немного пугали, пока не найден кардинальный метод:

emca -deconfig dbcontrol db
emca -config dbcontrol db

Об именах

Исследования в статье натолкнули на мысль собственных исследований.

Итак в оракле есть имена и параметры:

  • db_name -- имя базы, т.е. физического набора файла данных. Имя базы по словам Кайта прописывается в самих файлах.

  • db_domain -- никогда особо не понимал, зачем это нужно

  • instance_name -- имя экземпляра, т.е. набора процессов операционной системы и памяти.

  • db_unique_name -- уникальное имя базы, если db_name одинаковый (например в Standby). Именно это имя используется в папках во Flash recovery area

  • service_name -- имя сервиса, реалезуемое на экземпляре.


Исследования проводим на Oracle 11.1.0.6 путем изменения параметров, перезапуска базы и исследования результатов путем запуска скрипта:

shut immediate
startup nomount pfile=d:\init.ora

set feedback off
alter system register;

--host cls

col "name" format a20
column value format a40
SELECT name, value FROM v$parameter where name IN ('db_name', 'db_unique_name', 'db_domain', 'instance_name', 'service_names');

host lsnrctl services


База изначально создавалась как db1.notebook, т.е.

*.db_name='db1'
*.db_domain='notebook'


1. db_name = db1, остальные параметры не заданы

db_domain
instance_name db1
service_names db1
db_name db1
db_unique_name db1

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "db1" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "db1_XPT" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER


Без указания заданного при создании базы db_domain база нормально открылась

2. db_name = db2 (отличается от того, что задавался при создании)
NAME VALUE
-------------------- ----------------------------------------
db_domain
instance_name db1
service_names db2
db_name db2
db_unique_name db2

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "db2" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "db2_XPT" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
The command completed successfully


instance_name берется откуда-то еще, возможно из каких-то переменных среды или из сервиса
База не маунтится.

SQL> alter database mount;
alter database mount
*
ERROR at line 1:
ORA-01103: database name 'DB1' in control file is not 'DB2'


3. db_name=db1, db_domain=notebook

NAME VALUE
-------------------- ----------------------------------------
db_domain notebook
instance_name db1
service_names db1.notebook
db_name db1
db_unique_name db1

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "db1.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "db1_XPT.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
The command completed successfully


Таким образом service_name = db_name + db_domain

4. db_name=db1, db_domain=notebook, service_names = my_service

NAME VALUE
-------------------- ----------------------------------------
db_domain notebook
instance_name db1
service_names my_service
db_name db1
db_unique_name db1

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "db1.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "db1_XPT.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "my_service.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
The command completed successfully


service_names равен соответствующему параметру

5. db_name=db1, db_domain=notebook, instance_name = just_instance

NAME VALUE
-------------------- ----------------------------------------
db_domain notebook
instance_name just_instance
service_names db1.notebook
db_name db1
db_unique_name db1

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "db1.notebook" has 1 instance(s).
Instance "just_instance", status BLOCKED, has 1 handler(s) for this service...

Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "db1_XPT.notebook" has 1 instance(s).
Instance "just_instance", status BLOCKED, has 1 handler(s) for this service...

Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
The command completed successfully


instance_name поменялся и стал равен соответсвующему параметру.

6. db_name=db1, db_domain=notebook, db_unique_name=uniq

NAME VALUE
-------------------- ----------------------------------------
db_domain notebook
instance_name db1
service_names uniq.notebook
db_name db1
db_unique_name uniq

LSNRCTL for 32-bit Windows: Version 11.1.0.6.0 - Production on 23-APR-2011 02:47
:20

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

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "uniq.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "uniq_XPT.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
The command completed successfully


service_names = db_unique_name + db_domain

NAME VALUE
-------------------- ----------------------------------------
db_domain notebook
instance_name db1
service_names uniq.notebook
db_name db1
db_unique_name uniq

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "uniq.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
Service "uniq_XPT.notebook" has 1 instance(s).
Instance "db1", status BLOCKED, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
The command completed successfully


Выводы



1. service_names = COALESCE(service_names, db_unique_name || db_domain, db_name || db_domain) (точки писать не стал :))
2. instance_name = NVL(instance_name, что-то еще)
3. Без указания заданного при создании базы db_domain база нормально открылась

2011-04-21

Отслеживание процессов в Standby

Мониторниг передачи файлов на Primary:

  • V$ARCHIVED_LOG -- показывает, какие логи отправляются на STAND BY
  • V$ARCHIVE_DEST_STATUS -- состояние arch процессов, куда они отправляют файлы, последний отправленный файл
  • V$ARCHIVE_DEST -- аналогичен предыдущей вьюхе
  • alert log -- можно смотреть ошибки при отправке

Мониторниг приема и применения файлов в Standby

  • V$ARCHIVED_LOG (полученные логи), V$LOG_HISTORY (примененные логи), V$ARCHIVE_DEST_STATUS -- вьюхи, дающие с разным уровнем детализации последний полученный и последний применнный лог. Из последней вьюхи можно узнать ,в каком режиме применяются логи (real time или нет) в колонке RECOVERY_MODE.
  • Запущен ли процесс (должен существовать процесс MRP или MRP0)

SELECT PROCESS, STATUS FROM V$MANAGED_STANDBY;

  • V$DATAGUARD_STATUS -- информация из alert лога, можно узать полезное что-нибудь.

Для logical standby добавляются представления DBA_LOGSTDBY_*, V$LOGSTDBY_*

 

 

2011-04-18

Передача файлов

На StandBy необходимо сохранять следующие файлы:

  • архивы redo.log собственных (если logical standby)
  • архивы standby redo log (то, что передается с primary)
  • архивы переданных с primary архивов (если были проблемы со связью)
  • Отправлять никуда ничего не надо, до тех пор, пока база не получит роль Primary

В Primary необходимо

  • Делать архивы своих redo.log
  • Отправлять в stand by свои redo.log

Для управления этой кухней сделаны VALID_FOR (что сохраняем/отправляем, когда (при какой роли) сохраняем/отправляем)

Для что возможные значения: ONLINE_LOGFILE, STANDBY_LOGFILE, ALL_LOGFILES

Для когда возможные значения: PRIMARY_ROLE, STANDBY_ROLE, ALL_ROLES

Исходя из этого выводим:

1. Необходимо иметь возможность отправлять свои изменения по сети, т.е. должно быть настроено

VALID_FOR(ONLINE_LOGFILE, PRIMARY_ROLE) + указан сетевой сервис отправки

2. В качестве сохранения собственных изменений можно использовать Flash Recovery Area, которая по умолчанию настраивается в log_archive_dest_10. Если верить документации, то для log_archive_dest_10 будут настроены параметры по-умолчанию, т.е ALL_LOGFILES,ALL_ROLES. Но тут опять небольшая загвоздка в документации:

Flash recovery area destinations specified with the STANDBY_ARCHIVE_DEST parameter on logical standby databases (SQL Apply) are ignored

Таким образом, архивные логи, пришедшие с Primary в случае logical standby складировать некуда (если правильно понимаю документацию).

3. Т.к. ситуация со standby логами во flash recovery area в случае logical stand by не совсем понятна, возьмем, что оракл рекомендует использовать в документации:

Для Primary

LOG_ARCHIVE_DEST_1=
'LOCATION=/arch1/chicago/
VALID_FOR=(ALL_LOGFILES,ALL_ROLES)
LOG_ARCHIVE_DEST_2=
'LOCATION=/arch2/chicago/
VALID_FOR=(STANDBY_LOGFILES,STANDBY_ROLE)
STANDBY_ARCHIVE_DEST=/arch2/chicago/

Для Standby

LOG_ARCHIVE_DEST_1=
'LOCATION=/arch1/denver/
VALID_FOR=(ONLINE_LOGFILES,ALL_ROLES)
DB_UNIQUE_NAME=denver'
LOG_ARCHIVE_DEST_2=
'LOCATION=/arch2/denver/
VALID_FOR=(STANDBY_LOGFILES,STANDBY_ROLE)
STANDBY_ARCHIVE_DEST=/arch2/denver

Тут возникают непонятные моменты:

1. Почему log_archive_dest_1 на Primary и StandBy различаются.

2. А не складируются ли у нас Standby логи в Primary 2 раза, после смены ролей. Видимо в Primary должно быть:

LOG_ARCHIVE_DEST_1=
'LOCATION=/arch1/chicago/
VALID_FOR=(ONLINE_LOGFILES,ALL_ROLES)

Или же, если верить, что Flash Recorery Area и так сохраняет в себе все сгенеренные логи, достаточно добавить параметр STANDBY_ARCHIVE_DEST.

Наверное, лучше всего сконфигурировать 3 процесса и разбивать файлы на 2 кучки свои и чужие:

1. Посылатель файлов для Primary role

2. Раскладыватель online для всех ролей (1 кучка)

3. Раскладыватель standby логов для standby роли (вторая кучка). STANDBY_ARCHIVE_DEST, если не задан, будет указывать на вторую кучку аутоматически

Создание Standby общие идеи

На основании документации и статьи

Общие идеи

Подготовка primary

 

  1. База находится в режиме архивирования, есть password file.
  2. Перевести базу в режим force logging
  3. Опционально (если будет использоваться режим maximum protection и maximum aviablity, включен LGWR ASYNC transport mode). Этот случай не исследовался
  4. Изменить параметры базы данных. Можно делать alter system, можно через pfile с последующим перезапуском. Параметры применить перед снятием бекапа. Минимум параметров, которые необходимо задавать:
    • db_unique_name -- экземпляры открывают одну и туже базу данных, в которых db_name одинаковый. Параметры должны различаться в primary и standby. Что бы не было путаницы, лучше не называть с подчеркиваниями (oradim не может создать базу с sid содержащий подчеркивания), так же заводить в дальнейшем tnsnames с такой же строкой (service_name, совпадающий с идентификатором в tnsnames)
    • log_archive_config='dg_config=(db1_pri,db1_stb)' -- задаются db_unique_name, между которыми происходит обмен логами
    • LOG_ARCHIVE_DEST_1=  'SERVICE=db1stb VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)  DB_UNIQUE_NAME=db1_stb'
      LOG_ARCHIVE_DEST_STATE_1=ENABLE - т.к. у меня есть db_recovery_file_dest, то log_archive_dest_2 мне (наверное, перепроверить при измении ролей!!!) не нужен. В SERVICE указывается строка из tnsnames. Указывает, куда отсылаем логи.
    • FAL_SERVER='DB1STB'
      FAL_CLIENT='DB1'
      STANDBY_FILE_MANAGEMENT=auto -- параметры, необходимые при смене ролей primary
    • т.к. структура каталогов standby и primary  у меня совпадает, то параметры log_file_name_convert и db_file_name_convert я не указываю ни в primary, ни в standby. Вместо этого при разворачивании пользуюсь ключиком NOFILENAMECHECK
  5. Сделать бекап, из которого будем разворачивать standby, включая специальный бекап control file.
  6. Настроить tnsnames, прописав туда саму базу и standby-базу. Проверить tnsping правильность.

Подготовка standby

  1. Забираем с primary файлы:
    • tnsname.ora -- должен указывать и на primary и на standby
    • password (можно забрать и переименовать, можно создать новый)
    • pfile
    • бекапы - помещаем в тоже место, куда снимались в primary, хотя можно и рекоталагизировать.
    • redo логи, если они были созданы в primary (этот случай не рассматривался)
  2. Изменяем pfile
    • изменяем db_unique_name, см. примечания к этому в primary
    • control_files -- я закомментировал и он у меня создал контрольник в db_recovery_file_dest. В документации просто изменены пути
    • LOG_ARCHIVE_DEST_1=  'SERVICE=db1 VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=db1_pri'. Куда отправляем файлы в случае смены ролей. Относительно Primary изменилось SERVICE и DB_UNIQUE_NAME
  3. Создаем каталоги, аналогичные по структуре primary для указанных в файле параметров путей, а так же файлов базы данных.
  4. Создаем экземпляр при помощи oradim, создаем сервис listenera. При использовании oradim не получается создать sid базы с подчеркиванием. Проверить, что службы сами запускаются.
  5. Делаем или изменяем password file.
  6. Создаем spfile, Запускаем базу в режиме nomount. Если появляется ошибка ora-12560 сделать set oracle_sid = ...
  7. Разворачиваем созданный на primary бекап. Если структура каталогов та же, то используем команду duplicate target database for standby dorecover NOFILENAMECHECK, что бы не ругалась на дублирование имен файлов. Запускать rman необходимо на standby, или прописывать базу в листенере, что бы к ней можно было подключиться удаленно.
  8. Делаем alter database recover managed standby database disconnect;
  9. Проверяем передачу и накат логов.