Что делать, если нет дисковой полки под RAC, а синхронизацию БД Oracle в реальном времени обеспечить нужно? Настроить потоки данных Oracle (Oracle Streams)!
Про потоки данных написано много. Например, здесь, здесь и здесь, в том числе и в официальной документации. В данной статье описан вариант настроек без использования redo-логов, работающий для редакций Oracle Standard Edition One и Oracle Standard Edition 11gR2 (лицензия на Enterprise позволяет провести настройку проще, прямо в Enterprise Manager Console, см. ограничения).
Итак, стремимся к автоматическому перехвату DML операций во всех таблицах схемы HR и синхронизации данных в обе стороны:
- Настройка системных параметров БД:
sqlplus / as sysdba ALTER SYSTEM SET global_names = true scope= both; ALTER SYSTEM SET shared_pool_size = 256M scope= both; ALTER SYSTEM SET streams_pool_size = 256M scope= both; ALTER SYSTEM SET java_pool_size = 100M scope= both; ALTER SYSTEM SET parallel_max_servers= 10 scope= both;
- Настройка Oracle Net Services
tnsnames.ora:
ORCLA = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = host_a)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = orcla.local) ) ) ORCLB = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = host_b)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = orclb.local) ) )
- Создание табличного пространства администратора Streams:
mkdir C:Oracleapporadatastrems sqlplus / as sysdba -- Создать табличное пространство CREATE TABLESPACE streams_tbs DATAFILE 'C:Oracleapporadatastremsstreams_tbs.dbf' SIZE 25M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
- Cоздание администратора streams с привилегиями Oracle Streams:
sqlplus / as sysdba -- создать администратора Streams CREATE USER strmadmin IDENTIFIED BY "<пароль>" DEFAULT TABLESPACE streams_tbs QUOTA UNLIMITED ON streams_tbs; -- права на подключение GRANT CONNECT TO strmadmin; GRANT DBA TO strmadmin; BEGIN -- привилегии администратора Streams DBMS_STREAMS_AUTH.GRANT_ADMIN_PRIVILEGE( grantee => 'strmadmin', grant_privileges => TRUE); END; / execute MGMT_USER.MAKE_EM_USER('STRMADMIN');
- Создание связей баз данных (database links):
sqlplus strmadmin@orcla CREATE DATABASE LINK orclb CONNECT TO strmadmin IDENTIFIED BY "<пароль>" USING 'orclb'; sqlplus strmadmin@orclb CREATE DATABASE LINK orcla CONNECT TO strmadmin IDENTIFIED BY "<пароль>" USING 'orcla'; -- просмотреть связи базы данных SELECT * FROM ALL_DB_LINKS; -- протестировать связь базы данных SELECT * FROM DUAL@ORCLB; SELECT * FROM TAB@ORCLB;
- Создание очередей Streams, которые будут использоваться для хранения изменений в БД:
sqlplus strmadmin@orcla begin -- Создание очередей (4 ANYDATA queues at each database) dbms_streams_adm.set_up_queue@orcla( queue_table=> 'strmadmin.apply_queue_table_a', queue_name => 'strmadmin.apply_queue_a', queue_user => 'strmadmin'); dbms_streams_adm.set_up_queue@orcla( queue_table=> 'strmadmin.capture_queue_table_a', queue_name => 'strmadmin.capture_queue_a', queue_user => 'strmadmin'); dbms_streams_adm.set_up_queue@orclb( queue_table=> 'strmadmin.apply_queue_table_b', queue_name => 'strmadmin.apply_queue_b', queue_user => 'strmadmin'); dbms_streams_adm.set_up_queue@orclb( queue_table=> 'strmadmin.capture_queue_table_b', queue_name => 'strmadmin.capture_queue_b', queue_user => 'strmadmin'); end; /
- Создание процессов применения (Apply process):
sqlplus strmadmin@orcla begin -- Создание процессов применения dbms_apply_adm.create_apply@orcla( queue_name => 'strmadmin.apply_queue_a', apply_name => 'apply_a', source_database=> 'orclb', apply_captured => false); dbms_apply_adm.create_apply@orclb( queue_name => 'strmadmin.apply_queue_b', apply_name => 'apply_b', source_database=> 'orcla', apply_captured => false); end; /
- Настройка дополнительных параметров применения (подробнее):
sqlplus strmadmin@orcla begin -- не выключать процесс при возникновении ошибки dbms_apply_adm.set_parameter@orcla( apply_name => 'apply_a', parameter => 'disable_on_error', value => 'n'); dbms_apply_adm.set_parameter@orclb( apply_name => 'apply_b', parameter => 'disable_on_error', value => 'n'); -- проводить сравнение только по первичному ключу dbms_apply_adm.set_parameter@orcla( apply_name => 'apply_a', parameter => 'compare_key_only', value => 'y'); dbms_apply_adm.set_parameter@orclb( apply_name => 'apply_b', parameter => 'compare_key_only', value => 'y'); end; /
- Создание процессов синхронного сбора изменений таблиц (Synchronous capture):
sqlplus strmadmin@orcla SET SERVEROUTPUT ON DECLARE V_SN VARCHAR2(255); -- получить список всех таблиц схемы CURSOR GET_TABLES_CUR IS SELECT table_name FROM all_tables WHERE owner = '<название схемы синхронизируемой БД>' ORDER BY table_name; BEGIN DBMS_OUTPUT.ENABLE; -- название схемы V_SN := '<название схемы синхронизируемой БД>'; FOR V_GT IN GET_TABLES_CUR LOOP -- Создание синхронного сбора изменений всех таблиц схемы (Synchronous capture) dbms_streams_adm.add_table_rules@orcla( table_name => V_SN || '.' || V_GT.table_name, streams_type => 'sync_capture', streams_name => 'sca' || V_GT.table_name, queue_name => 'strmadmin.capture_queue_a', include_dml => true, include_ddl => false, source_database=> 'orcla'); dbms_streams_adm.add_table_rules@orclb( table_name => V_SN || '.' || V_GT.table_name, streams_type => 'sync_capture', streams_name => 'scb' || V_GT.table_name, queue_name => 'strmadmin.capture_queue_b', include_dml => true, include_ddl => false, source_database=> 'orclb'); END LOOP; COMMIT; END; /
- Процесс передачи изменений (Propagation process):
sqlplus strmadmin@orcla SET SERVEROUTPUT ON DECLARE V_SN VARCHAR2(255); CURSOR GET_TABLES_CUR IS SELECT table_name FROM all_tables WHERE owner = '<название схемы синхронизируемой БД>' ORDER BY table_name; BEGIN DBMS_OUTPUT.ENABLE; -- название схемы V_SN := '<название схемы синхронизируемой БД>'; FOR V_GT IN GET_TABLES_CUR LOOP -- Настройка передачи изменений dbms_streams_adm.add_table_propagation_rules@orcla( table_name => V_SN || '.' || V_GT.table_name, streams_name => 'prop_a', source_queue_name => 'strmadmin.capture_queue_a', destination_queue_name => 'strmadmin.apply_queue_b@orclb', source_database => 'orcla', queue_to_queue => true); dbms_streams_adm.add_table_propagation_rules@orclb( table_name => V_SN || '.' || V_GT.table_name, streams_name => 'prop_b', source_queue_name => 'strmadmin.capture_queue_b', destination_queue_name => 'strmadmin.apply_queue_a@orcla', source_database => 'orclb', queue_to_queue => true); END LOOP; COMMIT; END; /
- Первоначальная синхронизация таблиц (если необходимо):
-- удаление таблиц drop table "repl_user"."<имя удаляемой таблицы>"@orclb cascade constraints; -- создать ссылку на каталог на БД «b» create or replace directory b_dir as 'c:oracleapporadata'; -- получить SCN на БД «a» select owner, directory_name, directory_path from all_directories; -- синхронизация таблицы по сети select dbms_flashback.get_system_change_number@orcla() from dual; impdp strmadmin/<пароль>@orclb directory=b_dir network_link=orcla tables=<название схемы синхронизируемой БД>.<имя таблицы> flashback_scn=2025750
- Установка контрольных точек (необходимо для начала отчета перехвата изменений):
sqlplus strmadmin@orcla SET SERVEROUTPUT ON DECLARE V_SN VARCHAR2(255); CURSOR GET_TABLES_CUR IS SELECT table_name FROM all_tables WHERE owner = '<название схемы синхронизируемой БД>' ORDER BY table_name; iscn_a number; iscn_b number; BEGIN DBMS_OUTPUT.ENABLE; -- название схемы V_SN := '<название схемы синхронизируемой БД>'; iscn_a := dbms_flashback.get_system_change_number@orcla(); iscn_b := dbms_flashback.get_system_change_number@orclb(); FOR V_GT IN GET_TABLES_CUR LOOP -- Установка SCN для таблиц dbms_apply_adm.set_table_instantiation_scn@orcla( source_object_name => V_SN || '.' || V_GT.table_name, source_database_name => 'orclb', instantiation_scn => iscn_b); dbms_apply_adm.set_table_instantiation_scn@orclb( source_object_name => V_SN || '.' || V_GT.table_name, source_database_name => 'orcla', instantiation_scn => iscn_a); END LOOP; COMMIT; END; /
- Запуск процессов применения и передачи:
sqlplus strmadmin@orcla begin -- остановить все процессы dbms_apply_adm.stop_apply@orcla( apply_name => 'apply_a'); dbms_propagation_adm.stop_propagation@orcla( propagation_name=> 'prop_a', force => false); dbms_apply_adm.stop_apply@orclb( apply_name => 'apply_b'); dbms_propagation_adm.stop_propagation@orclb( propagation_name=> 'prop_b', force => false); -- запустить все процессы dbms_apply_adm.start_apply@orcla( apply_name => 'apply_a'); dbms_propagation_adm.start_propagation@orcla( propagation_name=> 'prop_a'); dbms_apply_adm.start_apply@orclb( apply_name => 'apply_b'); dbms_propagation_adm.start_propagation@orclb( propagation_name=> 'prop_b'); end; /
- Настройка завершена.
- Описание по отработке исключений приведено в «Troubleshooting Streams Apply Errors ORA-1403, ORA-26787 or ORA-26786,Conflict Resolution (Doc ID 265201.1)» и в «Streams Conflict Resolution (Doc ID 230049.1)»
Автор: enkidu