1.配置逻辑Standby 的准备工作
在创建逻辑standby之前,首先检查primary数据库的状态,确保primary数据库已经为创建逻辑standby做好了全部准备工作,比如说是否启动了归档是否启用了forced logging等,这部分可以参考创建物理standby时的准备工作,除此之外呢,由于逻辑standby是通过sql应用来保持与primary数据库的同步,sql应用与redo应用是有很的大区别,redo应用实际上是物理standby端进行recover,sql应用则是分析redo文件将其转换为sql语句在逻辑standby端执行,
1)检查数据库是否有不被逻辑standby支持的对象,如下:
SQL> SELECT * FROM DBA_LOGSTDBY_UNSUPPORTED;
OWNER TABLE_NAME COLUMN_NAME DATA_TYPE ATTRIBUTES
---------- -------------------- -------------------- -------------------- --------------------
SH MVIEW$_EXCEPTIONS BAD_ROWID ROWID
OE CUSTOMERS CUST_ADDRESS CUST_ADDRESS_TYP
OE CUSTOMERS PHONE_NUMBERS PHONE_LIST_TYP
OE CUSTOMERS CUST_GEO_LOCATION SDO_GEOMETRY
OE WAREHOUSES WAREHOUSE_SPEC XMLTYPE
OE WAREHOUSES WH_GEO_LOCATION SDO_GEOMETRY
PM ONLINE_MEDIA PRODUCT_AUDIO ORDAUDIO
PM ONLINE_MEDIA PRODUCT_TESTIMONIALS ORDDOC
PM ONLINE_MEDIA PRODUCT_PHOTO ORDIMAGE
PM ONLINE_MEDIA PRODUCT_PHOTO_SIGNATURE ORDIMAGESIGNATURE
PM ONLINE_MEDIA PRODUCT_THUMBNAIL ORDIMAGE
PM ONLINE_MEDIA PRODUCT_VIDEO ORDVIDEO
PM PRINT_MEDIA AD_TEXTDOCS_NTAB TEXTDOC_TAB
PM PRINT_MEDIA AD_GRAPHIC BFILE
PM PRINT_MEDIA AD_HEADER ADHEADER_TYP
OE CATEGORIES_TAB CATEGORY_NAME VARCHAR2 Object Table
OE CATEGORIES_TAB CATEGORY_DESCRIPTION VARCHAR2 Object Table
OE CATEGORIES_TAB CATEGORY_ID NUMBER Object Table
OE CATEGORIES_TAB PARENT_CATEGORY_ID NUMBER Object Table
19 rows selected.
批注:关于DBA_LOGSTDBY_UNSUPPORTED 该视图显示包含不被支持的数据类型的表的列名及该列的数据类型,注意该视图的ATTRIBUTES列,列值会显示表不被sql应用支持的原因。
2)维护逻辑standby与primary的数据库同步是通过sql应用实现,SQL应用转换的SQL语句在执行时,对于insert还好说,对于update,delete操作则必须能够唯一定位到数据库待更新的那条记录,问题就在这里,如果primary库中表设置不当,可能就无法确认唯一条件,逻辑standby跟物理standby的区别,就是因为它只是逻辑上与primary数据库相同,郑州牛皮癣医院物理上可能与primary数据库存在相当大差异,一定要认识到,逻辑standby的物理结构与primary是不相同的(即使初始逻辑standby是通过primary的备份创建),因此想通过rowid更新显然是不好使的,就不能再将其做为唯一条件,可以通过以下的方法来解决:
如何确保primary库中各表的行可被唯一标识
Oracle 通过主键、唯一索引/约束补充日志(supplemental logging)来确定待更新逻辑standby库中的行,当数据库启用了补充日志(supplemental logging)每一条update语句写redo的时候会附加列值唯一信息,比如:
如果表定义了主键,则主键值会随同被更新列一起做为update语句的一部分,以便执行时区别哪些列应该被更新;
如果没有主键,则非空的唯一索引/约束会随同被更新列做为update语句的一部分,以便执行时区分哪些列应该被更新,如果该表有多个唯一索引/约束,则oracle自动选择最短的那个;
如果表即无主键,也没有定义唯一索引/约束,所有可定长度的列连同被更新列作为update语句的一部分,更明确的话可定长度的列是指那些除:long,lob,long raw,object type,collection类型外的列;
确定在主数据库上,补充日志是否被启用,可以查询v$database,如下:SQL> select SUPPLEMENTAL_LOG_DATA_FK,SUPPLEMENTAL_LOG_DATA_ALL,SUPPLEMENTAL_LOG_DATA_MIN from v$database;
SUP SUP SUPPLEME
--- --- --------
NO NO NO
SQL> ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
Database altered.
SQL> select SUPPLEMENTAL_LOG_DATA_FK,SUPPLEMENTAL_LOG_DATA_ALL,SUPPLEMENTAL_LOG_DATA_MIN from v$database;
SUP SUP SUPPLEME
--- --- --------
NO NO YES
批注:SUPPLEMENTAL_LOG_DATA_MIN=YES和IMPLICIT都表示数据库启动了最小化的补充日志。YES表示通过ALTER DATABASE ADD SUPPLEMENTAL LOG DATA语句启动的最小化补充日志;如果启动了对主键、唯一键、外键、ALL的补充日志,默认情况下都会打开最小化的补充日志,IMPLICIT表示的是通过启动对主键、唯一键、外键或者ALL的支持而打开的最小化补充日志。
因此,Oracle 建议你为表创建一个主键或非空的唯一索引/约束,以尽可能确保sql应用能够有效应用redo数据更新逻辑standby数据库。
3)执行下列语句检查sql应用能否唯一识别表列,找出不被支持的表:
SQL> SELECT OWNER, TABLE_NAME FROM DBA_LOGSTDBY_NOT_UNIQUE
2 WHERE (OWNER, TABLE_NAME) NOT IN
3 (SELECT DISTINCT OWNER, TABLE_NAME FROM DBA_LOGSTDBY_UNSUPPORTED)
4 AND BAD_COLUMN = 'Y';
OWNER TABLE_NAME
------------------------------ ------------------------------
TSMSYS SRS$ --这是一张系统表,首先查看该用户是否可以登录,如果是锁定状态,我们就无需设置它
SQL> select username,account_status from dba_users where username like '%TSMSYS%';
USERNAME ACCOUNT_STATUS
------------------------------ --------------------------------
TSMSYS EXPIRED & LOCKED
批注:DBA_LOGSTDBY_NOT_UNIQUE 该视图显示包含不被支持的数据类型,即既没有主键,也没有唯一索引的表,如果表中的列包括足够多的信息通常也可支持在逻辑standby的更新,不被支持的表通常是由于列的定义包含了不支持的数据类型。
对于BAD_COLUMN 列值有两个:
Y:表示该表中有采用大数据类型的字段,比如LONG,CLOB,如果表中除log列某些行记录完全匹配,则该表无法成功应用于逻辑standby,standby会尝试维护这些表,不过你必须保证应用不允许;
N:表示该表拥有足够的信息,能够支持在逻辑standby的更新,郑州牛皮癣专科医院不过仍然建议你为该表创建一个主键或者唯一索引/约束以提高log应用效率;
4)假设某张表你可以确认数据是唯一的,但是因为效率方面的考虑,不想为其创建主键或唯一约束,怎么办呢,没关系,oracle想到了这一点,你可以创建一个disable的primary-key rely约束:
关于primary-key RELY约束:
如果你能够确认表中的行是唯一的,那么可以为该表创建rely的主键,RELY约束并不会造成系统维护主键的开销,如果你对一个表创建了rely约束,系统则会假定该表中的行是唯一,这样能够提供sql应用时的性能,但是需要注意,由于rely的主键约束只是假定唯一,如果实际并不唯一的话,有可能会造成错误的更新。
创建rely的主键约束非常简单,只要在标准的创建语句后加上RELY DISABLE即可,示例如下:
SQL> ALTER TABLE mytab ADD PRIMARY KEY (id, name) RELY DISABLE; --表mytab为我要创建rely主键约束的表名
2.创建逻辑standby
为了方便区分当前操作的数据库,设置一下操作符,如下:
SQL> set sqlprompt primary> --表示primary数据库
SQL> set sqlprompt lgstandby> --表示standby数据库
1)在物理standby上取消redo apply :
lgstandby>ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
批注:如果决定将其转换为逻辑standby,就必须停止该物理standby的redo应用,以避免提前应用含LogMiner 字典的redo 数据,造成转换为逻辑standby 后,sql 应用时logMiner 字典数据不足而影响到逻辑standby 与primary 的正常同步。
2)设置primary数据库
[oracle@xiaoru app]$ mkdir my_arch2
[oracle@xiaoru app]$ ls
admin flash_recovery_area my_arch my_arch2 oracle oradata oraInventory
primary>alter system set LOG_ARCHIVE_DEST_3='LOCATION=/u01/app/my_arch2/ VALID_FOR=(STANDBY_LOGFILES,STANDBY_ROLE)
2 DB_UNIQUE_NAME=orcl' LOG_ARCHIVE_DEST_STATE_3=ENABLE SCOPE=BOTH ;
System altered.
primary>show parameter LOG_ARCHIVE_DEST_3;
NAME TYPE VALUE
--------------------- ----------- ------------------------------
log_archive_dest_3 string LOCATION=/u01/app/my_arch2/ VALID_FOR=(STANDBY_LOGFILES,STANLID_FOR=(
STANDBY_LOGFILES,STANDBY_ROLE) DB_UNIQUE_NAME=orcl
执行如下语句,生成LogMiner字典信息:
primary>EXECUTE DBMS_LOGSTDBY.BUILD;
PL/SQL procedure successfully completed.
批注:该过程专门用于生成记录的元数据信息到redo log,这样改动才会被传输到逻辑standby,然后才会被逻辑standby 进行SQL 应用。该过程通过闪回查询的方式来获取数据字典的一致性,因此oracle初始化参数UNDO_RETENTION值需要设置的足够大。
3)转换物理standby为逻辑standby
lgstandby>show parameter db_name;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_name string myorcl
lgstandby>ALTER DATABASE RECOVER TO LOGICAL STANDBY lg_myorcl;
ALTER DATABASE RECOVER TO LOGICAL STANDBY lg_myorcl
*
ERROR at line 1:
ORA-02084: database name is missing a component
ORACLE10G官网查看错误分析,截图如下:
批注:感觉我也没有使用里面不允许的特殊字符啊,不解;
lgstandby>ALTER DATABASE RECOVER TO LOGICAL STANDBY lgmyorcl; --不让用就不用呗,多简单的事啊,这不是也哦了吗
Database altered.
批注:逻辑standby是一个全新的数据库,如果当前使用spfile,则数据库会自动修改其中的相关信息,如果使用的是pfile,在下次执行shutdown的时候oracle会提示你去修改db_name初始化参数的值。
4)重启standby数据库
lgstandby>shutdown immediate
lgstandby>startup mount;
lgstandby>show parameter db_name; --查看db_name
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_name string LGMYORCL
lgstandby>select name,database_role,open_mode from v$database;
NAME DATABASE_ROLE OPEN_MODE
--------- ---------------- ----------
LGMYORCL LOGICAL STANDBY MOUNTED
5)打开逻辑standby
由于逻辑standby与primary数据库事务并不一致,因此第一次打开时必须指定resetlogs选择,如下:
lgstandby>alter database open resetlogs;
Database altered.
然后执行如下SQL语句打开redo应用:
lgstandby>alter database start logical standby apply immediate;
Database altered.
3.验证
1)首先查询主、备库中scott用户下的表,如下:
primary>conn scott/tiger;
Connected.
primary>select * from tab;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
DEPT TABLE
EMP TABLE
BONUS TABLE
SALGRADE TABLE
lgstandby>conn scott/tiger;
Connected.
lgstandby>select * from tab;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
DEPT TABLE
EMP TABLE
BONUS TABLE
SALGRADE TABLE
2)主库中创建表mydept,并为其添加主键约束,如下
primary>create table mydept as select * from dept;
Table created.
primary>alter table mydept add constraints pk_d primary key (deptno);
Table altered.
primary>select * from tab;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
DEPT TABLE
EMP TABLE
BONUS TABLE
SALGRADE TABLE
MYDEPT TABLE
primary>select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE from user_constraints where table_name='MYDEPT';
TABLE_NAME CONSTRAINT_NAME C
------------------------------ ------------------------------ -
MYDEPT PK_D P
primary>conn / as sysdba
Connected.
primary>alter system switch logfile; --切换日志
System altered.
3)备库查看主库在scott用户下创建的mydept表是否同步
lgstandby>select * from tab;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
DEPT TABLE
EMP TABLE
BONUS TABLE
SALGRADE TABLE
MYDEPT TABLE
lgstandby>select TABLE_NAME,CONSTRAINT_NAME,CONSTRAINT_TYPE from user_constraints where table_name='MYDEPT';
TABLE_NAME CONSTRAINT_NAME C
------------------------------ ------------------------------ -
MYDEPT PK_D P
4)主库上对表mydept执行DML语句,示例如下:
primary>conn scott/tiger
Connected.
primary>delete mydept where deptno=10;
1 row deleted.
primary>select * from mydept;
DEPTNO DNAME LOC
---------- -------------- -------------
50 ORACLE JAVA
60 dayong xiaoru
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
primary>commit;
Commit complete.
primary>conn / as sysdba;
Connected.
primary>alter system switch logfile;
System altered.
5)备库查询数据是否同步
lgstandby>show user;
USER is "SCOTT"
lgstandby>select * from mydept;
DEPTNO DNAME LOC
---------- -------------- -------------
50 ORACLE JAVA
60 dayong xiaoru
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
批注:由查询结果可知,备库已经成功同步,至此,物理standby转为逻辑standby已经完成
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29661313/viewspace-1178879/ ,如需转载,请注明出处,否则将追究法律责任。