?
?
第三部分邏輯standby(4)高級管理? 2008.03.04
?
?
一、監(jiān)控邏輯standby
?
??? 與物理standby 的管理一樣,oracle 提供了一系列動態(tài)性能視圖來查看邏輯standby 的狀態(tài),有一些我們前面已經(jīng)接觸過,而有一些,我們還從未用過。。。。。
?
1、DBA_LOGSTDBY_EVENTS
?
??? 可以把該視圖看成邏輯standby 操作日志,因此如果發(fā)生了錯誤,可以通過該視圖查看近期邏輯standby都做了些什么。默認情況下, 該視圖保留100 條事件的記錄, 不過你可以通過DBMS_LOGSTDBY.APPLY_SET()過程修改該參數(shù)。
?
??? 例如:
??? JSSLDG2> select event_time,status,event from dba_logstdby_events;
??? EVENT_TIME ???????? STATUS ?????????????????? ??????????????? EVENT
??? ------------------- ----------------------------------------- ----------------------------------------
??? 2008-03-06 08:58:11 ORA-16112: 日志挖掘和應(yīng)用正在停止
??? 2008-03-06 09:02:00 ORA-16111: 日志挖掘和應(yīng)用正在啟動
??? 2008-03-06 09:52:53 ORA-16128: 已成功完成用戶啟動的停止應(yīng)用操作
??? 2008-03-12 15:52:53 ORA-16111: 日志挖掘和應(yīng)用正在啟動
??? 2008-03-12 16:09:17 ORA-16226: 由于不支持而跳過DDL ???????????? ALTER DATABASEOPEN
??? 2008-03-05 17:21:46 ORA-16111: 日志挖掘和應(yīng)用正在啟動
??? ..............................
?
2、DBA_LOGSTDBY_LOG
?
??? 該視圖用來記錄當(dāng)前的歸檔日志應(yīng)用情況,等同于物理standby 中的v$archived_log,多數(shù)情況下,你只需要關(guān)注SEQUENCE#,APPLIED,即查看日志序號和是否應(yīng)用,當(dāng)然該視圖還能提供更多信息,比如應(yīng)用的scn,應(yīng)用時間等,例如:
??? 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
?
??? 通常情況下,該查詢只會返回幾條記錄,如果說你的數(shù)據(jù)庫操作非常頻繁,可能記錄數(shù)會稍多一些,但如果記錄數(shù)非常多,那你可能就需要關(guān)注一下,是不是出了什么問題,難道sql 應(yīng)用沒有啟動?
?
3、V$LOGSTDBY_STATS
??? 從名字就大致猜的出來,該視圖顯示的是狀態(tài)信息,沒錯,你猜對了,該視圖就是用來顯示LogMiner的統(tǒng)計信息及狀態(tài)。
??? 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
?
??? 該視圖顯示當(dāng)前l(fā)og 應(yīng)用服務(wù)的相關(guān)信息。常用于診斷歸檔日志邏輯應(yīng)用的性能問題(后面優(yōu)化部分會有涉及),包含的信息也很廣:
??? ※ 身份信息:SID,SERIAL#,SPID
??? ※ SQL 應(yīng)用進程:COORDINATOR, READER, BUILDER, PREPARER, ANALYZER, 或APPLIER
??? ※ 進程當(dāng)前的狀態(tài):見status_code 或status 列
??? ※ 該進程當(dāng)前操作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 應(yīng)用服務(wù)當(dāng)前進展?fàn)顩r,比如當(dāng)前應(yīng)用到邏輯standby 的scn 及時間,sql 應(yīng)用開始應(yīng)用的scn 及時間,最后接收及應(yīng)用的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 應(yīng)用的大致狀態(tài),比如primary 庫的dbid 啦,是否啟動了實時應(yīng)用啦,當(dāng)前sql 應(yīng)用的狀態(tài)啦之類。
?
??? 注意state 列,該列可能有下述的幾種狀態(tài):
??? ※ INITIALIZING: LogMiner session 已創(chuàng)建并初始化
??? ※ LOADING DICTIONARY: SQL 應(yīng)用調(diào)用LogMiner 字典
??? ※ WAITING ON GAP: SQL 應(yīng)用正等待日志文件,可能有中斷
??? ※ APPLYING: SQL 應(yīng)用正在工作
??? ※ WAITING FOR DICTIONARY LOGS: SQL 應(yīng)用等待LogMiner 字典信息
??? ※ IDLE: SQL 應(yīng)用工作非常出色,已經(jīng)干的沒什么可干了:)
?
??? 例如:
??? JSSLDG2> select * from v$Logstdby_state;
??? PRIMARY_DBID SESSION_ID REALTIME_APPLY ????? STATE
??? ------------ ---------- -------------------- ----------------------
??? 3408827880 ? 42 ??????? Y ?????????????????? APPLYING
?
?
二、管理邏輯standby
1、接收到的歸檔文件
??? 前章曾經(jīng)提到,邏輯standby 應(yīng)用完歸檔后會自動刪除該歸檔文件,該特性你如果覺著不爽,沒關(guān)系,執(zhí)行下面這個過程,屏蔽掉它:
??? JSSLDG2> EXECUTE DBMS_LOGSTDBY.APPLY_SET('LOG_AUTO_DELETE', FALSE);
?
??? 提示:這種操作并非毫無意義,比如說邏輯standby 打開了flashback database,那如果你想恢復(fù)到之前的某個時間點,然后再接著應(yīng)用,就必須要有該時間點后對應(yīng)的歸檔,假如LOG_AUTO_DELETE 為TRUE的話,顯然應(yīng)用過的歸檔就不存在了,想回都回不去。
?
2、啟動實時應(yīng)用
?
??? 默認情況下,log 應(yīng)用服務(wù)會等待單個歸檔文件全部接收之后再啟動應(yīng)用(在前面redo 傳輸服務(wù)中我們介紹了不同形式的傳輸方式),如果standby 端使用了standby redologs,就可以打開實時應(yīng)用(real-time apply),這樣dg 就不需要再等待接收完歸檔文件,只要rfs 將redo 數(shù)據(jù)寫入standby redologs,即可通過MRP/LSP
實時寫向standby,這樣就可以盡可能保持standby 與primary 的同步。
?
??? 要啟動邏輯standby 的實時應(yīng)用,只需要在啟動邏輯standby 應(yīng)用時加上immediate 子句即可,前面我們已經(jīng)無數(shù)次的演練過,例如:
??? JSSLDG2> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
?
3、定義DBA_EVENTDBA_LOGSTDBY_EVENTS視圖中事件記錄的相關(guān)參數(shù)。
?
??? Dba_logstdby_events 視圖前面剛講過,里面記錄了邏輯standby 的一些操作事件,如果你希望修改該視圖中記錄的事件信息的話,可以通過下列的方式:
?
??? 例如,希望該視圖能夠保留最近999 條事件,可以通過執(zhí)行下列語句:
??? JSSLDG2> select *from v$logstdby_stats where name='maximum events recorded';
??? NAME ??????????????????????????????????????? VALUE
??? -------------------------------------------- ---------------
??? maximum events recorded ???????????????????? 100
??? JSSLDG2> alter database stop logical standby apply;
??? 數(shù)據(jù)庫已更改。
??? JSSLDG2> execute?dbms_logstdby.apply_set('max_events_recorded','999');
??? PL/SQL 過程已成功完成。
??? JSSLDG2> alter database start logical standby apply immediate;
??? 數(shù)據(jù)庫已更改。
??? JSSLDG2> select *from v$logstdby_stats where name='maximum events recorded';
??? NAME ??????????????????????????????????????? VALUE
??? -------------------------------------------- ---------------
??? maximum events recorded ???????????????????? 999
?
??? 再比如,你如果想在視圖中記錄ddl 操作的信息,可以通過執(zhí)行下列語句:
??? JSSLDG2> execute dbms_logstdby.apply_set('RECORD_APPLIED_DDL','TRUE');
?
4、指定對象跳過應(yīng)用,請用DBMS_LOGSTDBY.SKIP
??? 默認情況下,接收自primary 的redo 數(shù)據(jù)中,所有能夠被standby 支持的操作都會在邏輯standby 端執(zhí)行,如果你希望跳過對某些對象的某些操作的話,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 外,其它都是可選參數(shù),并且看字面意義就能明白其所指,下面簡單描述一下stmt 參數(shù)調(diào)用的關(guān)鍵字都是指定值,詳細見下列:
?
STMT關(guān)鍵字
|
包含的操作
|
NON_SCHEMA_DDL
|
不屬于模式對象的所有其它ddl操作
|
提示:使用該關(guān)鍵字時,SCHEMA_NAME和OBJECT_NAME兩參數(shù)也必須指定。
|
SCHEMA_DDL
|
創(chuàng)建修改刪除模式對象的所有ddl操作(例如: tables, indexes, and columns)
|
提示:使用該關(guān)鍵字時,SCHEMA_NAME和OBJECT_NAME兩參數(shù)也必須指定。
|
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 操作,可以通過執(zhí)行下列語句實現(xiàn)(執(zhí)行該過程前需要先停止redo 應(yīng)用):
??? JSSLDG2> alter database stop logical standby apply;
??? 數(shù)據(jù)庫已更改。
??? JSSLDG2> executedbms_logstdby.skip('DML','JSS','TMP1');
??? PL/SQL 過程已成功完成。
??? JSSLDG2> alter database start logical standby apply;
??? 數(shù)據(jù)庫已更改。
??? 提示:DBMS_LOGSTDBY.SKIP 的功能非常強大,限于篇幅,這里僅舉示例,而且由于其操作非常靈活,此篇俺也不可能就其用法做個一一列舉,因此,更豐富的操作方式就留待看官們下頭自行發(fā)現(xiàn)去吧:)
?
三、修改邏輯standby端數(shù)據(jù)
??? 我們前面提到,邏輯standby 一個極具實用價值的特性即是可以邊查詢邊應(yīng)用,因此將其做為報表服務(wù)器專供查詢是個很不錯的想法,而且邏輯standby 相對于物理standby 而言更具靈活性,比如我們可以在邏輯standby上,對一些表創(chuàng)建primary 庫上并不方便創(chuàng)建的索引,約束,甚至可以做dml,ddl 操作(當(dāng)然,需要注意不要破壞了與primary 之間同步的邏輯關(guān)系)。不過由于此時dg 仍然控制著對邏輯standby 表的讀寫操作,因此,如果你想對邏輯standby 中的數(shù)據(jù)做些什么的話,alter session database disable|enable guard 語句就必須牢記在心了,它擁有像“芝麻開門”一樣神奇的能力,不信?下面我們就來感受一下吧。
?
1、邏輯standby端執(zhí)行ddl
?
??? 在邏輯standby 端開始了redo 應(yīng)用的情況下,執(zhí)行ddl 操作:
??? JSSLDG2> create table tmp55 as select * From b;
??? create table tmp55 as select * From b
??? *
??? 第1 行出現(xiàn)錯誤:
??? ORA-01031: 權(quán)限不足
??? 看看,出錯了吧~~~
??? JSSLDG2> alter session disable guard;
??? 會話已更改。
??? JSSLDG2> create table tmp55 as select * From b;
??? 表已創(chuàng)建。
??? 只有關(guān)閉了guard 保護之后,才能操作數(shù)據(jù),然后別忘了再啟用guard,以避免不經(jīng)意的操作對邏輯standby 的配置造成影響。
??? JSSLDG2> alter session enable guard;
??? 會話已更改。
?
??? 提示:oracle 建議還是盡可能不要在邏輯standby 執(zhí)行執(zhí)行dml 之類操作,以免破解其與primary 之間同步的邏輯關(guān)系,當(dāng)然,這只是個建議,如果你已經(jīng)仔細看完了3.1 章,并且對數(shù)據(jù)庫表結(jié)構(gòu)及存儲結(jié)構(gòu)了如指掌,那您就愛干嘛愛嘛。
?
2、取消對象同步
??? 如果說,某些表或者數(shù)據(jù)不需要dataguard 保護(比如一些在邏輯standby 端生成的統(tǒng)計表),這個時候就需要DBMS_LOGSTDBY.SKIP,前頭已經(jīng)介紹過了dbms_logstdby.skip 的基本用法,下面我們來具體演示一下!
??? 下面我們假設(shè)standby 端有一批表名為tmp 開頭的表,這張表不再需要保持與primary 的同步,那么按照步驟執(zhí)行下列語句,sql 應(yīng)用即可跳過這些表:
?
??? 老規(guī)矩,先停了redo 應(yīng)用
??? JSSLDG2> alter database stop logical standby apply;
??? 數(shù)據(jù)庫已更改。
??? 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;
??? 數(shù)據(jù)庫已更改。
?
??? 注意其中的%,該符號為通配符,作用與在sql 語句中的相同。
?
??? OK,下面來測試一下,先看看邏輯standby 中表的信息,我們選擇兩張表,一張是我們前面已經(jīng)指定了跳過的表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 數(shù)據(jù)庫執(zhí)行插入操作
??? JSSWEB> select max(aa) from jss.tmp1;
??? Max(aa)
??? --------------------
??? h
??? JSSWEB> insert into jss.tmp1 values ('i');
??? 已創(chuàng)建1 行。
??? JSSWEB> insert into jss.b values (10);
??? 已創(chuàng)建1 行。
??? JSSWEB> commit;
??? 提交完成。
??? JSSWEB> alter system switch logfile;
??? 系統(tǒng)已更改。
??? JSSWEB> select max(sequence#) from v$archived_log;
??? MAX(SEQUENCE#)
??? --------------
??? 873
?
??? 再來看看邏輯standby 端的同步情況:
??? JSSLDG2> select sequence#,applied from dba_logstdby_log;
??? SEQUENCE# APPLIED
??? ---------- --------
??? 873 ?????? YES
?
??? 顯然日志已經(jīng)接收,再看看數(shù)據(jù):
??? JSSLDG2> select max(id) from b;
??? Max(id)
??? ----------
??? 10
??? JSSLDG2> select max(aa) from jss.tmp1;
??? Max(aa)
??? --------------------
??? h
?
??? b 表已應(yīng)用,而tmp1 表則無變化。
?
3、恢復(fù)對象同步
??? 如果說某些表某個時候取消了同步,現(xiàn)在希望再恢復(fù)同步,沒問題,DBMS_LOGSTDBY 家大業(yè)大,它還有個叫UNSKIP 的門生就是專干這個的。
?
??? 我們來看一下dbms_logstdby.unskip 的語法:
??? DBMS_LOGSTDBY.UNSKIP (
??? stmt ??????? IN VARCHAR2,
??? schema_name IN VARCHAR2,
??? object_name IN VARCHAR2);
?
??? 三項均為必選參數(shù),各參數(shù)的定義與skip 過程相同,這里不再復(fù)述。
?
??? 此處我們來演示恢復(fù)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;
??? 數(shù)據(jù)庫已更改。
??? JSSLDG2> execute dbms_logstdby.unskip('DML','JSS','TMP1');?--本步操作是為解決歷史遺留問題,不用關(guān)注
??? PL/SQL 過程已成功完成。
??? JSSLDG2> executexecute?dbms_logstdby.unskip('DML','JSS','TMP%');
??? PL/SQL 過程已成功完成。
??? JSSLDG2> execute
??? dbms_logstdby.unskip('SCHEMA_DDL','JSS','TMP%');
??? PL/SQL 過程已成功完成。
??? 跳過同步已經(jīng)取消了,緊接著我們需要再調(diào)用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 過程重新執(zhí)行一下同步(執(zhí)行前別忘了暫停redo 應(yīng)用):
??? 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 行。
?
??? 數(shù)據(jù)已重建,下面測試一下該表的redo 應(yīng)用是否恢復(fù)了。
??? JSSWEB> insert into jss.tmp1 values ('j');
??? 已創(chuàng)建1 行。
??? JSSWEB> insert into jss.tmp1 values ('k');
??? 已創(chuàng)建1 行。
??? JSSWEB> commit;
??? 提交完成。
??? JSSWEB> alter system switch logfile;
??? 系統(tǒng)已更改。
??? JSSWEB> select max(sequence#) from v$archived_log;
??? MAX(SEQUENCE#)
??? --------------
??? 877
?
??? 啟動邏輯standby 端的redo 應(yīng)用,看看對象的應(yīng)用情況:
??? JSSLDG2> alter database start logical standby apply immediate;
??? 數(shù)據(jù)庫已更改。
??? 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,恢復(fù)正常啦!
?
??? 注意喲,此處我們清楚明白的知道我們之前只操作了tmp1 一張表,如果是正式應(yīng)用的話,那你恐怕有必要將所有tmp 開頭的表都同步一下,不然有可能會造成數(shù)據(jù)丟失的喲。
?
四、特殊事件的控制
??? 時間緊任務(wù)急,呵呵,這里三思就只描述流程,過程就不做演示了,相信你的智力,你一定能看懂。
?
1、導(dǎo)入傳輸表空間
?
??? ※ 第一步:屏蔽guard 保護,邏輯standby 端操作
??? SQL> ALTER SESSION DISABLE GUARD;
?
??? ※ 第二步:導(dǎo)入傳輸表空間,邏輯standby 端操作
??? 具體操作步驟可參考三思之前的筆記:使用可傳輸表空間的特性復(fù)制數(shù)據(jù)!
?
??? ※ 第三步:恢復(fù)guard 保護(或者直接退出本session 也成),邏輯standby 端操作
??? SQL> ALTER SESSION ENABLE GUARD;
?
??? ※ 第四步:導(dǎo)入傳輸表空間,primary 端操作
??? 同第二步。
?
2、使用物化視圖
?
??? SQL 應(yīng)用不支持下列對物化視圖的ddl 操作:
??? ※ create/alter/drop materialized view
??? ※ create/alter/drop materialized view log
?
??? 因此,對于現(xiàn)有邏輯standby,primary 端對物化視圖的操作不會傳播到standby 端。不過,對于primary創(chuàng)建物化視圖之后創(chuàng)建邏輯standby,則物理視圖也會存在于邏輯standby 端。
?
??? ※ 對于同時存在于primary 和邏輯standby 的ON-COMMIT 物化視圖,邏輯standby 會在事務(wù)提交時自動刷新,而對于ON-DEMAND 的物化視圖不會自動刷新,需要手動調(diào)用dbms_mview.refresh 過程刷新。
??? ※ 對于邏輯standby 端建立的ON-COMMIT 物化視圖會自動維護,ON-DEMAND 物化視圖也還是需要手工調(diào)用dbms_mview.refresh 過程刷新。
?
3、觸發(fā)器及約束的運作方式
?
??? 默認情況下,約束和觸發(fā)器同樣會在邏輯standby 端正常工作。
?
??? 對于有sql 應(yīng)用維護的約束和觸發(fā)器:
??? ※ 約束:由于約束在primary 已經(jīng)檢查過,因此standby 端不需要再次檢查
??? ※ 觸發(fā)器:primary 端操作時結(jié)果被記錄,在standby 端直接被應(yīng)用。
?
??? 沒有sql 應(yīng)用維護的約束和觸發(fā)器:
??? ※ 約束有效
??? ※ 觸發(fā)器有效
?
?
五、優(yōu)化邏輯standbstandby
?
1、創(chuàng)建PrimaryKeyRELY約束
?
??? 某些情況下能夠有效提高sql 應(yīng)用效率,具體可參見第三部分第一章。
?
2、生成統(tǒng)計信息
?
??? 這個很容易理解嘛,因為cbo 要用,生成方式即可用analyze,也可以用dbms_stats 包。看你個人喜好了。
?
3、調(diào)整進程數(shù)
?
???
A).調(diào)整APPLIER進程數(shù)
?
??? 首先查看當(dāng)前空閑的applier 進程數(shù):
??? JSSLDG2> SELECT COUNT(*) AS IDLE_APPLIER FROM V$LOGSTDBY_PROCESS
?????????? 2 WHERE TYPE = 'APPLIER' and status_code = 16166;
??? IDLE_APPLIER
??? ------------
??? 0
?
??? 提示:
??? status_code = 16166 表示進程是空閑狀態(tài),可以看到"STATS"為"ORA-16116: no work available",當(dāng)然空閑的applier 進程數(shù)為0 不一定代表應(yīng)用應(yīng)用非常繁忙,也有可能是因為當(dāng)前沒什么需要應(yīng)用的日志,因此甚至應(yīng)用進程都沒啟動:)
?
??? 檢查事務(wù)的應(yīng)用情況:
??? JSSLDG2> select name,value from v$logstdby_stats where name like 'TRANSACTION%';
??? NAME ???????????????? VALUE
??? --------------------- -------
??? transactions ready ?? 896
??? transactions applied 871
?
??? 如果ready-applied 的值比applier 進程數(shù)的兩倍還要大,則說明你有必要考慮增加applier 進程的數(shù)目了,反之如果applied 與ready 的值差不多大,或者其差比applier 進程數(shù)還小,則說明applier 進程數(shù)偏多,你有必要考慮適當(dāng)減小進程的數(shù)目。
??? 如果確認當(dāng)前applier 進程都非常繁忙,要增加applier 進程,可按如下步驟操作:
?
??? 停止sql 應(yīng)用
??? ALTER DATABASE STOP LOGICAL STANDBY APPLY;
?
??? 調(diào)整applier 進程數(shù)為20,默認是5 個
??? EXECUTE DBMS_LOGSTDBY.APPLY_SET('APPLY_SERVERS', 20);
?
??? 重啟sql 應(yīng)用
??? ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;
?
??? B).調(diào)整PREPARER進程數(shù)
??? 需要調(diào)整preparer 進程數(shù)的機會不多,通常只有一種情況:applier 進程有空閑,transactions ready 還很多,但沒有空閑的preparer 進程,這時候你可能需要增加一些preparer 進程。
??? 要檢查系統(tǒng)是否存在這種情況,可以通過下列的sql 語句:
?
??? 首先檢查空閑preparer 進程數(shù)量:
??? SELECT COUNT(*) AS IDLE_PREPARER FROM V$LOGSTDBY_PROCESS WHERE TYPE ='PREPARER' and status_code = 16166;
?
??? 檢查事務(wù)的應(yīng)用情況:
??? select name,value from v$logstdby_stats where name like 'TRANSACTION%';
??? 查看當(dāng)前空閑的applier 進程數(shù):
??? SELECT COUNT(*) AS IDLE_APPLIER FROM V$LOGSTDBY_PROCESS WHERE TYPE = 'APPLIER'and status_code = 16166;
?
??? 如果確實需要調(diào)整preparer 進程數(shù)量,可以按照下列步驟,例如:
?
??? 停止sql 應(yīng)用
??? ALTER DATABASE STOP LOGICAL STANDBY APPLY;
??? 調(diào)整preparer 進程數(shù)量為4(默認只有1 個preparer 進程)
??? EXECUTE DBMS_LOGSTDBY.APPLY_SET('PREPARE_SERVERS', 4);
??? 重啟sql 應(yīng)用
??? ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;
4、調(diào)整LCR使用的內(nèi)存
??? 執(zhí)行下列語句,查詢當(dāng)前LCR 可用的最大內(nèi)存:
??? JSSLDG2> select * from v$logstdby_stats where name='maximum SGA for LCR cache';
??? NAME ??????????????????????????????? VALUE
??? ------------------------------------ --------------------
??? maximum SGA for LCR cache ?????????? 30
?
??? 要增加LCR 可用的內(nèi)存,按照下列步驟操作:
?
??? 停止sql 應(yīng)用:
??? JSSLDG2> alter database stop logical standby apply;
??? 數(shù)據(jù)庫已更改。
?
??? 調(diào)整內(nèi)存大小,注意默認單位是M:
??? JSSLDG2> execute dbms_logstdby.apply_set('MAX_SGA',100);
??? PL/SQL 過程已成功完成。
?
??? 重啟sql 應(yīng)用
??? JSSLDG2> alter database start logical standby apply immediate;
??? 數(shù)據(jù)庫已更改。
?
5、調(diào)整事務(wù)應(yīng)用方式
??? 默認情況下邏輯standby 端事務(wù)應(yīng)用順序與primary 端提交順序相同。
?
??? 如果你希望邏輯standby 端的事務(wù)應(yīng)用不要按照順序的話,可以按照下列的步驟操作:
???
①
停止
sql
應(yīng)用
:
??? SQL> ALTER DATABASE STOP LOGICAL STANDBYAPPLY;
?
???
②
允許事務(wù)不按照
primary
的提交順序應(yīng)用
??? SQL> EXECUTE DBMS_LOGSTDBY.APPLY_SET('PRESERVE_COMMIT_ORDER', 'FALSE');
?
???
③
重新啟動
sql
應(yīng)用
??? SQL> ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;
?
?
??? 恢復(fù)邏輯standby 按照事務(wù)提交順序應(yīng)用的話,按照下列步驟:
???
①
還是先停止
sql
應(yīng)用:
??? SQL> ALTER DATABASE STOP LOGICAL STANDBYAPPLY;
?
???
②
重置參數(shù)
PRESERVE_COMMIT_ORDER
的初始值:
??? SQL> EXECUTE DBMS_LOGSTDBY.APPLY_UNSET('PRESERVE_COMMIT_ORDER');
?
???
③
重新啟動
sql
應(yīng)用:
??? SQL> ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;
?
?