您的位置:首页 > 其它

一步一步学DataGuard(18)逻辑standby之高级管理3

2008-04-15 15:13 375 查看
一、 修改逻辑standby端数据
我们前面提到,逻辑standby一个极具实用价值的特性即是可以边查询边应用,因此将其做为报表服务器专供查询是个很不错的想法,而且逻辑standby相对于物理standby而言更具灵活性,比如我们可以在逻辑standby上,对一些表创建primary库上并不方便创建的索引,约束,甚至可以做dml,ddl操作(当然,需要注意不要破坏了与primary之间同步的逻辑关系)。不过由于此时dg仍然控制着对逻辑standby表的读写操作,因此,如果你想对逻辑standby中的数据做些什么的话,alter session database disable|enable guard语句就必须牢记在心了,它拥有像“芝麻开门”一样神奇的能力,不信?下面我们就来感受一下吧。

1、 逻辑standby端执行ddl
在逻辑standby端开始了redo应用的情况下,执行ddl操作:
JSSLDG2> create table tmp55 as select * From b;
create table tmp55 as select * From b
*
第 1 行出现错误:
ORA-01031: 权限不足
看看,出错了吧~~~

JSSLDG2> alter session disable guard;

会话已更改。

JSSLDG2> create table tmp55 as select * From b;

表已创建。
只有关闭了guard保护之后,才能操作数据,然后别忘了再启用guard,以避免不经意的操作对逻辑standby的配置造成影响。

JSSLDG2> alter session enable guard;

会话已更改。

提示:oracle建议还是尽可能不要在逻辑standby执行执行dml之类操作,以免破解其与primary之间同步的逻辑关系,当然,这只是个建议,如果你已经仔细看完了3.1章,并且对数据库表结构及存储结构了如指掌,那您就爱干嘛爱嘛。

2、 取消对象同步
如果说,某些表或者数据不需要dataguard保护(比如一些在逻辑standby端生成的统计表),这个时候就需要DBMS_LOGSTDBY.SKIP,前头已经介绍过了dbms_logstdby.skip的基本用法,下面我们来具体演示一下!
下面我们假设standby端有一批表名为tmp开头的表,这张表不再需要保持与primary的同步,那么按照步骤执行下列语句,sql应用即可跳过这些表:
老规矩,先停了redo应用
JSSLDG2> alter database stop logical standby apply;

数据库已更改。

JSSLDG2> execute dbms_logstdby.skip('SCHEMA_DDL','JSS','TMP%');
--跳过对象的ddl操作
PL/SQL 过程已成功完成。

JSSLDG2> execute dbms_logstdby.skip('DML','JSS','TMP%');
--跳过对象的dml操作
PL/SQL 过程已成功完成。

JSSLDG2> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;

数据库已更改。
注意其中的%,该符号为通配符,作用与在sql语句中的相同。
OK,下面来测试一下,先看看逻辑standby中表的信息,我们选择两张表,一张是我们前面已经指定了跳过的表tmp1,另一张是普通表b:
JSSLDG2> select max(aa) from jss.tmp1;

Max(aa)
--------------------
h

JSSLDG2> select max(id) from jss.b;

Max(id)
----------
9

JSSLDG2> select sequence#,applied from dba_logstdby_log;

SEQUENCE# APPLIED
---------- --------
872 YES
然后在primary数据库执行插入操作

JSSWEB> select max(aa) from jss.tmp1;

Max(aa)
--------------------
h

JSSWEB> insert into jss.tmp1 values ('i');

已创建 1 行。

JSSWEB> insert into jss.b values (10);

已创建 1 行。

JSSWEB> commit;

提交完成。

JSSWEB> alter system switch logfile;

系统已更改。

JSSWEB> select max(sequence#) from v$archived_log;

MAX(SEQUENCE#)
--------------
873

再来看看逻辑standby端的同步情况:
JSSLDG2> select sequence#,applied from dba_logstdby_log;

SEQUENCE# APPLIED
---------- --------
873 YES

显然日志已经接收,再看看数据:
JSSLDG2> select max(id) from b;

Max(id)
----------
10

JSSLDG2> select max(aa) from jss.tmp1;

Max(aa)
--------------------
h

b表已应用,而tmp1表则无变化。

3、 恢复对象同步
如果说某些表某个时候取消了同步,现在希望再恢复同步,没问题,DBMS_LOGSTDBY家大业大,它还有个叫UNSKIP的门生就是专干这个的。
我们来看一下dbms_logstdby.unskip的语法:
DBMS_LOGSTDBY.UNSKIP (
stmt IN VARCHAR2,
schema_name IN VARCHAR2,
object_name IN VARCHAR2);
三项均为必选参数,各参数的定义与skip过程相同,这里不再复述。
此处我们来演示恢复tmp%表的同步。

JSSLDG2> select *from dba_logstdby_skip;

ERROR STATEMENT_OPT OWNER NAME U E PROC
----- --------------- ---------- --------------- - - --------------------
N SCHEMA_DDL JSS TMP% Y
N DML JSS TMP% Y
N DML JSS TMP1 Y
........

JSSLDG2> alter database stop logical standby apply;

数据库已更改。

JSSLDG2> execute dbms_logstdby.unskip('DML','JSS','TMP1');
--本步操作是为解决历史遗留问题,不用关注
PL/SQL 过程已成功完成。

JSSLDG2> execute dbms_logstdby.unskip('DML','JSS','TMP%');

PL/SQL 过程已成功完成。

JSSLDG2> execute dbms_logstdby.unskip('SCHEMA_DDL','JSS','TMP%');

PL/SQL 过程已成功完成。

跳过同步已经取消了,紧接着我们需要再调用dbms_logstdby.instantiate_table过程重新同步一下跳地的对象,将skip这段时间,primary对tmp1表所做的操作同步过来(就俺看来,instantiate_table过程实际上是借助dblink重建了一遍对象),以保持与primary的一致。Dbms_logstdby.instantiate_table的语法如下:
DBMS_LOGSTDBY.INSTANTIATE_TABLE (
schema_name IN VARCHAR2,
table_name IN VARCHAR2,
dblink IN VARCHAR2);

使用DBMS_LOGSTDBY.INSTANTIATE_TABLE过程重新执行一下同步(执行前别忘了暂停redo应用):

JSSLDG2> EXECUTE DBMS_LOGSTDBY.INSTANTIATE_TABLE('JSS','TMP1','GETJSSWEB');

PL/SQL 过程已成功完成。

JSSLDG2> select *from jss.tmp1;

AA
--------------------
a
b
c
d
e
f
g
h
i

已选择9行。

数据已重建,下面测试一下该表的redo应用是否恢复了。
JSSWEB> insert into jss.tmp1 values ('j');

已创建 1 行。

JSSWEB> insert into jss.tmp1 values ('k');

已创建 1 行。

JSSWEB> commit;

提交完成。

JSSWEB> alter system switch logfile;

系统已更改。

JSSWEB> select max(sequence#) from v$archived_log;

MAX(SEQUENCE#)
--------------
877

启动逻辑standby端的redo应用,看看对象的应用情况:
JSSLDG2> alter database start logical standby apply immediate;

数据库已更改。

JSSLDG2> select sequence#,applied from dba_logstdby_log;

SEQUENCE# APPLIED
---------- --------
875 YES
876 YES
877 YES

JSSLDG2> select *from jss.tmp1;

AA
--------------------
a
b
c
d
e
f
g
h
i
j
k

已选择11行。
OK,恢复正常啦!

注意哟,此处我们清楚明白的知道我们之前只操作了tmp1一张表,如果是正式应用的话,那你恐怕有必要将所有tmp开头的表都同步一下,不然有可能会造成数据丢失的哟。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: