第三部分逻辑standby(4)高级管理 2008.03.04
一、监控逻辑standby
与物理standby 的管理一样,oracle 提供了一系列动态性能视图来查看逻辑standby 的状态,有一些我们前面已经接触过,而有一些,我们还从未用过。。。。。
1、DBA_LOGSTDBY_EVENTS
可以把该视图看成逻辑standby 操作日志,因此如果发生了错误,可以通过该视图查看近期逻辑standby都做了些什么。默认情况下, 该视图保留100 条事件的记录, 不过你可以通过DBMS_LOGSTDBY.APPLY_SET()过程修改该参数。
例如:
JSSLDG2> select event_time,status,event from dba_logstdby_events;
EVENT_TIME STATUS EVENT
------------------- ----------------------------------------- ----------------------------------------
2008-03-06 08:58:11 ORA-16112: 日志挖掘和应用正在停止
2008-03-06 09:02:00 ORA-16111: 日志挖掘和应用正在启动
2008-03-06 09:52:53 ORA-16128: 已成功完成用户启动的停止应用操作
2008-03-12 15:52:53 ORA-16111: 日志挖掘和应用正在启动
2008-03-12 16:09:17 ORA-16226: 由于不支持而跳过DDL ALTER DATABASEOPEN
2008-03-05 17:21:46 ORA-16111: 日志挖掘和应用正在启动
..............................
2、DBA_LOGSTDBY_LOG
该视图用来记录当前的归档日志应用情况,等同于物理standby 中的v$archived_log,多数情况下,你只需要关注SEQUENCE#,APPLIED,即查看日志序号和是否应用,当然该视图还能提供更多信息,比如应用的scn,应用时间等,例如:
JSSLDG2> select sequence#,first_change#,next_change#,timestamp,applied from dba_logstdby_log;
SEQUENCE# FIRST_CHANGE# NEXT_CHANGE# TIMESTAMP APPLIED
---------- ------------- ------------ ------------------- --------
869 1319212 1319811 2008-03-12 16:09:15 CURRENT
通常情况下,该查询只会返回几条记录,如果说你的数据库操作非常频繁,可能记录数会稍多一些,但如果记录数非常多,那你可能就需要关注一下,是不是出了什么问题,难道sql 应用没有启动?
3、V$LOGSTDBY_STATS
从名字就大致猜的出来,该视图显示的是状态信息,没错,你猜对了,该视图就是用来显示LogMiner的统计信息及状态。
JSSLDG2> select *from v$logstdby_stats;
NAME VALUE
---------------------------------------- ---------------
number of preparers 1
number of appliers 5
maximum SGA for LCR cache 30
parallel servers in use 9
maximum events recorded 100
preserve commit order TRUE
transaction consistency FULL
record skip errors Y
record skip DDL Y
record applied DDL N
.........................
4、V$PROCESV$LOGSTDBY_PROCESS
该视图显示当前log 应用服务的相关信息。常用于诊断归档日志逻辑应用的性能问题(后面优化部分会有涉及),包含的信息也很广:
※ 身份信息:SID,SERIAL#,SPID
※ SQL 应用进程:COORDINATOR, READER, BUILDER, PREPARER, ANALYZER, 或APPLIER
※ 进程当前的状态:见status_code 或status 列
※ 该进程当前操作redo 记录最大SCN:high_scn 列
例如:
JSSLDG2> select sid,serial#,spid,type,status,high_scn from v$logstdby_process;
SID SERIAL# SPID TYPE STATUS HIGH_SCN
-------- ------- -------- --------------- ----------------------------------------------- ----------
145 1 508 COORDINATOR ORA-16116: 无可用工作 1319811
146 2 2464 READER ORA-16240: 正在等待日志文件(线程号1,序列号870) 1319811
143 1 1512 BUILDER ORA-16116: 无可用工作 1319742
142 1 4000 PREPARER ORA-16116: 无可用工作 1319741
139 1 2980 ANALYZER ORA-16116: 无可用工作 1319707
135 1 1648 APPLIER ORA-16116: 无可用工作 1319430
138 1 2332 APPLIER ORA-16116: 无可用工作 1319439
132 1 2200 APPLIER ORA-16116: 无可用工作 1319443
134 1 4020 APPLIER ORA-16116: 无可用工作
...........................................
5、V$PROGRESV$LOGSTDBY_PROGRESS
该视图显示log 应用服务当前进展状况,比如当前应用到逻辑standby 的scn 及时间,sql 应用开始应用的scn 及时间,最后接收及应用的scn 和时间等等。
例如:
JSSLDG2> select * from v$Logstdby_progress;
APPLIED_SCN APPLIED_TIME RESTART_SCN RESTART_TIME LATEST_SCNLATEST_TIME MINING_SCN MINING_TIME
----------- ------------------- ----------- ------------------- ---------- ------------------- ---------- -------------------
1319810 2008-03-12 16:06:51 1319662 2008-03-12 16:03:22 1319810 2008-03-12 16:45:331319811 2008-03-12 16:06:51
6、V$LOGSTDBY_STATE
该视图就最简单了,就是显示sql 应用的大致状态,比如primary 库的dbid 啦,是否启动了实时应用啦,当前sql 应用的状态啦之类。
注意state 列,该列可能有下述的几种状态:
※ INITIALIZING: LogMiner session 已创建并初始化
※ LOADING DICTIONARY: SQL 应用调用LogMiner 字典
※ WAITING ON GAP: SQL 应用正等待日志文件,可能有中断
※ APPLYING: SQL 应用正在工作
※ WAITING FOR DICTIONARY LOGS: SQL 应用等待LogMiner 字典信息
※ IDLE: SQL 应用工作非常出色,已经干的没什么可干了:)
例如:
JSSLDG2> select * from v$Logstdby_state;
PRIMARY_DBID SESSION_ID REALTIME_APPLY STATE
------------ ---------- -------------------- ----------------------
3408827880 42 Y APPLYING
二、管理逻辑standby
1、接收到的归档文件
前章曾经提到,逻辑standby 应用完归档后会自动删除该归档文件,该特性你如果觉着不爽,没关系,执行下面这个过程,屏蔽掉它:
JSSLDG2> EXECUTE DBMS_LOGSTDBY.APPLY_SET('LOG_AUTO_DELETE', FALSE);
提示:这种操作并非毫无意义,比如说逻辑standby 打开了flashback database,那如果你想恢复到之前的某个时间点,然后再接着应用,就必须要有该时间点后对应的归档,假如LOG_AUTO_DELETE 为TRUE的话,显然应用过的归档就不存在了,想回都回不去。
2、启动实时应用
默认情况下,log 应用服务会等待单个归档文件全部接收之后再启动应用(在前面redo 传输服务中我们介绍了不同形式的传输方式),如果standby 端使用了standby redologs,就可以打开实时应用(real-time apply),这样dg 就不需要再等待接收完归档文件,只要rfs 将redo 数据写入standby redologs,即可通过MRP/LSP
实时写向standby,这样就可以尽可能保持standby 与primary 的同步。
要启动逻辑standby 的实时应用,只需要在启动逻辑standby 应用时加上immediate 子句即可,前面我们已经无数次的演练过,例如:
JSSLDG2> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
3、定义DBA_EVENTDBA_LOGSTDBY_EVENTS视图中事件记录的相关参数。
Dba_logstdby_events 视图前面刚讲过,里面记录了逻辑standby 的一些操作事件,如果你希望修改该视图中记录的事件信息的话,可以通过下列的方式:
例如,希望该视图能够保留最近999 条事件,可以通过执行下列语句:
JSSLDG2> select *from v$logstdby_stats where name='maximum events recorded';
NAME VALUE
-------------------------------------------- ---------------
maximum events recorded 100
JSSLDG2> alter database stop logical standby apply;
数据库已更改。
JSSLDG2> execute dbms_logstdby.apply_set('max_events_recorded','999');
PL/SQL 过程已成功完成。
JSSLDG2> alter database start logical standby apply immediate;
数据库已更改。
JSSLDG2> select *from v$logstdby_stats where name='maximum events recorded';
NAME VALUE
-------------------------------------------- ---------------
maximum events recorded 999
再比如,你如果想在视图中记录ddl 操作的信息,可以通过执行下列语句:
JSSLDG2> execute dbms_logstdby.apply_set('RECORD_APPLIED_DDL','TRUE');
4、指定对象跳过应用,请用DBMS_LOGSTDBY.SKIP
默认情况下,接收自primary 的redo 数据中,所有能够被standby 支持的操作都会在逻辑standby 端执行,如果你希望跳过对某些对象的某些操作的话,DBMS_LOGSTDBY.SKIP 就能被派上用场了。
先来看看dbms_logstdby.skip 的语法:
DBMS_LOGSTDBY.SKIP (
stmt IN VARCHAR2,
schema_name IN VARCHAR2 DEFAULT NULL,
object_name IN VARCHAR2 DEFAULT NULL,
proc_name IN VARCHAR2 DEFAULT NULL,
use_like IN BOOLEAN DEFAULT TRUE,
esc IN CHAR1 DEFAULT NULL);
除stmt 外,其它都是可选参数,并且看字面意义就能明白其所指,下面简单描述一下stmt 参数调用的关键字都是指定值,详细见下列:
STMT关键字
|
包含的操作
|
NON_SCHEMA_DDL
|
不属于模式对象的所有其它ddl操作
|
提示:使用该关键字时,SCHEMA_NAME和OBJECT_NAME两参数也必须指定。
|
SCHEMA_DDL
|
创建修改删除模式对象的所有ddl操作(例如: tables, indexes, and columns)
|
提示:使用该关键字时,SCHEMA_NAME和OBJECT_NAME两参数也必须指定。
|
DML
|
Includes DML statements on a table (for example: INSERT, UPDATE, and DELETE)
|
CLUSTER
|
AUDIT CLUSTER
|
CREATE CLUSTER
|
DROP CLUSTER
|
TRUNCATE CLUSTER
|
CONTEXT
|
CREATE CONTEXT
|
DROP CONTEXT
|
DATABASE LINK
|
CREATE DATABASE LINK
|
CREATE PUBLIC DATABASE LINK
|
DROP DATABASE LINK
|
DROP PUBLIC DATABASE LINK
|
DIMENSION
|
ALTER DIMENSION
|
CREATE DIMENSION
|
DROP DIMENSION
|
DIRECTORY
|
CREATE DIRECTORY
|
DROP DIRECTORY
|
INDEX
|
ALTER INDEX
|
CREATE INDEX
|
DROP INDEX
|
PROCEDURE
|
ALTER FUNCTION
|
ALTER PACKAGE
|
ALTER PACKAGE BODY
|
ALTER PROCEDURE
|
CREATE FUNCTION
|
CREATE LIBRARY
|
CREATE PACKAGE
|
CREATE PACKAGE BODY
|
CREATE PROCEDURE
|
DROP FUNCTION
|
DROP LIBRARY
|
DROP PACKAGE
|
DROP PACKAGE BODY
|
DROP PROCEDURE
|
PROFILE
|
ALTER PROFILE
|
CREATE PROFILE
|
DROP PROFILE
|
ROLE
|
ALTER ROLE
|
CREATE ROLE
|
DROP ROLE
|
SET ROLE
|
ROLLBACK STATEMENT
|
ALTER ROLLBACK SEGMENT
|
CREATE ROLLBACK SEGMENT
|
DROP ROLLBACK SEGMENT
|
SEQUENCE
|
ALTER SEQUENCE
|
CREATE SEQUENCE
|
DROP SEQUENCE
|
SYNONYM
|
CREATE PUBLIC SYNONYM
|
CREATE SYNONYM
|
DROP PUBLIC SYNONYM
|
DROP SYNONYM
|
TABLE
|
ALTER TABLE
|
CREATE TABLE
|
DROP TABLE
|
TABLESPACE
|
CREATE TABLESPACE
|
DROP TABLESPACE
|
TRUNCATE TABLESPACE
|
TRIGGER
|
ALTER TRIGGER
|
CREATE TRIGGER
|
DISABLE ALL TRIGGERS
|
DISABLE TRIGGER
|
DROP TRIGGER
|
ENABLE ALL TRIGGERS
|
ENABLE TRIGGER
|
TYPE
|
ALTER TYPE
|
ALTER TYPE BODY
|
CREATE TYPE
|
CREATE TYPE BODY
|
DROP TYPE
|
DROP TYPE BODY
|
USER
|
ALTER USER
|
CREATE USER
|
DROP USER
|
VIEW
|
CREATE VIEW
|
DROP VIEW
|
例如,你想跳过jss 用户下对tmp1 表的dml 操作,可以通过执行下列语句实现(执行该过程前需要先停止redo 应用):
JSSLDG2> alter database stop logical standby apply;
数据库已更改。
JSSLDG2> executedbms_logstdby.skip('DML','JSS','TMP1');
PL/SQL 过程已成功完成。
JSSLDG2> alter database start logical standby apply;
数据库已更改。
提示:DBMS_LOGSTDBY.SKIP 的功能非常强大,限于篇幅,这里仅举示例,而且由于其操作非常灵活,此篇俺也不可能就其用法做个一一列举,因此,更丰富的操作方式就留待看官们下头自行发现去吧:)
三、修改逻辑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> executexecute dbms_logstdby.skip('SCHEMA_DDL','JSS','TMP%'); --跳过对象的ddl 操作
PL/SQL 过程已成功完成。
JSSLDG2> executedbms_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> executexecute 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 开头的表都同步一下,不然有可能会造成数据丢失的哟。
四、特殊事件的控制
时间紧任务急,呵呵,这里三思就只描述流程,过程就不做演示了,相信你的智力,你一定能看懂。
1、导入传输表空间
※ 第一步:屏蔽guard 保护,逻辑standby 端操作
SQL> ALTER SESSION DISABLE GUARD;
※ 第二步:导入传输表空间,逻辑standby 端操作
具体操作步骤可参考三思之前的笔记:使用可传输表空间的特性复制数据!
※ 第三步:恢复guard 保护(或者直接退出本session 也成),逻辑standby 端操作
SQL> ALTER SESSION ENABLE GUARD;
※ 第四步:导入传输表空间,primary 端操作
同第二步。
2、使用物化视图
SQL 应用不支持下列对物化视图的ddl 操作:
※ create/alter/drop materialized view
※ create/alter/drop materialized view log
因此,对于现有逻辑standby,primary 端对物化视图的操作不会传播到standby 端。不过,对于primary创建物化视图之后创建逻辑standby,则物理视图也会存在于逻辑standby 端。
※ 对于同时存在于primary 和逻辑standby 的ON-COMMIT 物化视图,逻辑standby 会在事务提交时自动刷新,而对于ON-DEMAND 的物化视图不会自动刷新,需要手动调用dbms_mview.refresh 过程刷新。
※ 对于逻辑standby 端建立的ON-COMMIT 物化视图会自动维护,ON-DEMAND 物化视图也还是需要手工调用dbms_mview.refresh 过程刷新。
3、触发器及约束的运作方式
默认情况下,约束和触发器同样会在逻辑standby 端正常工作。
对于有sql 应用维护的约束和触发器:
※ 约束:由于约束在primary 已经检查过,因此standby 端不需要再次检查
※ 触发器:primary 端操作时结果被记录,在standby 端直接被应用。
没有sql 应用维护的约束和触发器:
※ 约束有效
※ 触发器有效
五、优化逻辑standbstandby
1、创建PrimaryKeyRELY约束
某些情况下能够有效提高sql 应用效率,具体可参见第三部分第一章。
2、生成统计信息
这个很容易理解嘛,因为cbo 要用,生成方式即可用analyze,也可以用dbms_stats 包。看你个人喜好了。
3、调整进程数
A).调整APPLIER进程数
首先查看当前空闲的applier 进程数:
JSSLDG2> SELECT COUNT(*) AS IDLE_APPLIER FROM V$LOGSTDBY_PROCESS
2 WHERE TYPE = 'APPLIER' and status_code = 16166;
IDLE_APPLIER
------------
0
提示:
status_code = 16166 表示进程是空闲状态,可以看到"STATS"为"ORA-16116: no work available",当然空闲的applier 进程数为0 不一定代表应用应用非常繁忙,也有可能是因为当前没什么需要应用的日志,因此甚至应用进程都没启动:)
检查事务的应用情况:
JSSLDG2> select name,value from v$logstdby_stats where name like 'TRANSACTION%';
NAME VALUE
--------------------- -------
transactions ready 896
transactions applied 871
如果ready-applied 的值比applier 进程数的两倍还要大,则说明你有必要考虑增加applier 进程的数目了,反之如果applied 与ready 的值差不多大,或者其差比applier 进程数还小,则说明applier 进程数偏多,你有必要考虑适当减小进程的数目。
如果确认当前applier 进程都非常繁忙,要增加applier 进程,可按如下步骤操作:
停止sql 应用
ALTER DATABASE STOP LOGICAL STANDBY APPLY;
调整applier 进程数为20,默认是5 个
EXECUTE DBMS_LOGSTDBY.APPLY_SET('APPLY_SERVERS', 20);
重启sql 应用
ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;
B).调整PREPARER进程数
需要调整preparer 进程数的机会不多,通常只有一种情况:applier 进程有空闲,transactions ready 还很多,但没有空闲的preparer 进程,这时候你可能需要增加一些preparer 进程。
要检查系统是否存在这种情况,可以通过下列的sql 语句:
首先检查空闲preparer 进程数量:
SELECT COUNT(*) AS IDLE_PREPARER FROM V$LOGSTDBY_PROCESS WHERE TYPE ='PREPARER' and status_code = 16166;
检查事务的应用情况:
select name,value from v$logstdby_stats where name like 'TRANSACTION%';
查看当前空闲的applier 进程数:
SELECT COUNT(*) AS IDLE_APPLIER FROM V$LOGSTDBY_PROCESS WHERE TYPE = 'APPLIER'and status_code = 16166;
如果确实需要调整preparer 进程数量,可以按照下列步骤,例如:
停止sql 应用
ALTER DATABASE STOP LOGICAL STANDBY APPLY;
调整preparer 进程数量为4(默认只有1 个preparer 进程)
EXECUTE DBMS_LOGSTDBY.APPLY_SET('PREPARE_SERVERS', 4);
重启sql 应用
ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;
4、调整LCR使用的内存
执行下列语句,查询当前LCR 可用的最大内存:
JSSLDG2> select * from v$logstdby_stats where name='maximum SGA for LCR cache';
NAME VALUE
------------------------------------ --------------------
maximum SGA for LCR cache 30
要增加LCR 可用的内存,按照下列步骤操作:
停止sql 应用:
JSSLDG2> alter database stop logical standby apply;
数据库已更改。
调整内存大小,注意默认单位是M:
JSSLDG2> execute dbms_logstdby.apply_set('MAX_SGA',100);
PL/SQL 过程已成功完成。
重启sql 应用
JSSLDG2> alter database start logical standby apply immediate;
数据库已更改。
5、调整事务应用方式
默认情况下逻辑standby 端事务应用顺序与primary 端提交顺序相同。
如果你希望逻辑standby 端的事务应用不要按照顺序的话,可以按照下列的步骤操作:
①
停止
sql
应用
:
SQL> ALTER DATABASE STOP LOGICAL STANDBYAPPLY;
②
允许事务不按照
primary
的提交顺序应用
SQL> EXECUTE DBMS_LOGSTDBY.APPLY_SET('PRESERVE_COMMIT_ORDER', 'FALSE');
③
重新启动
sql
应用
SQL> ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;
恢复逻辑standby 按照事务提交顺序应用的话,按照下列步骤:
①
还是先停止
sql
应用:
SQL> ALTER DATABASE STOP LOGICAL STANDBYAPPLY;
②
重置参数
PRESERVE_COMMIT_ORDER
的初始值:
SQL> EXECUTE DBMS_LOGSTDBY.APPLY_UNSET('PRESERVE_COMMIT_ORDER');
③
重新启动
sql
应用:
SQL> ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;