Oracle 数据库复制常用脚本 Oracle的数据复制是一个Oracle数据库产品中比较成熟的一项技术,它是整个分布式计算解决方案的一个重要组成部分。 对于具有复制环境的数据库系统,和Oracle DBA一样,同样要有一个人来专门负责维护Oracle的数据复制问题,称之为Oracle Replication Administrator(Oracle复制治理员)。本文就Oracle数据复制中复制治理员经常关心的一些关于复制系统的问题,编写了不同的存储过程。当然,通过Oracle提供的复制治理器也可以达到这些目的,但在实际应用中,Oracle复制治理器具有不灵活,速度慢,同时我们不能对其查询结果进行随意控制等等的缺点。一、查看Oracle8x延迟事务队列调用及调用个数IT我最牛-程序员的技术讨论与分享园地U Zh:uwC*f [` 推(push)一个大的延迟事务(Deferred Transactions)队列是非常慢的。一个常见的问题就是一个事务中含有非常多的调用(calls)。假如系统检测到一个错误,如ora-01403(数据未找到错误),也就是我们常说的检测到冲突,而且没有冲突消除方法,写到deferror错误表和回滚事务的时间就会更长,事务中假如调用calls很多,则消耗在任何一个调用的时间就会以指数形式增长。对于数据复制中每个事务的调用数Oracel强烈建议不超过50个。下面的存储过程提供了一个快速查看延迟事务队列中的事务列表以及每个事务中调用数的脚本。输出是以传输顺序排列的,这个顺序就是事务将要传播到主节点的顺序。这对于确定传播中的延迟以及挂起等是非常有帮助的。在搭建Oracle数据复制环境中,有一个经验是值得注重的,那就是一定要设置冲突解决方案,即可使用Oracle系统提供的几种方案,也可以自己编写脚本来完成冲突处理。为什么这样说,一定要设置冲突解决方案,也许我们可以说,我们的复制环境是一个单项复制,不可能出现冲突现象。在这里我讲一个自己的亲身经历的例子来说明这个问题,在实际工作中,我搭建了一个具有15个节点的高级复制环境,一个主定义节点,14个主节点,其中14个主节点向主定义节点单向传递数据。一般来讲这种情况下不会出现冲突。但是在实际应用中,问题就出现了,其中几个节点在传输了一些数据后,就挂(hang)了起来。所有可能查找的原因到查了,始终发现不了问题的根结。最后发现是由于数据传播到远程节点后,出现了错误,而在该节点又没有设置冲突解决方案,同时出现错误的该事务又具有超过1000条的调用。其中有一条调用出错了,事务需要回滚,而这个在本地和远程节点间的回滚时间就会以几何基数增长。就出现了前面谈到的系统挂起(hang)的表现。这也就是说即是在根本不可能出现冲突的系统中,由于偶然的不定的错误进程,批量数据的处理以及没有考虑复制情况下的数据导入都可造成在传播过程中严重的性能问题,最严重的情况就是系统挂起,不能完成正常的复制工作。最简单和有效的办法就是在多路复制环境下设置一个系统确省的冲突处理方法来避免这种情况的发生。下面这个存储过程就是在Oracle 8 环境下列出延迟事务队列中的事务和事务中调用个数的脚本,该脚本对Oracle 7 不支持,这是因为Oracle 8 和Oracle 7 的复制机制发生了变化。存储过程调用方法:在SQL/PLUS下,首先运行下面的设置,使存储过程的输出到屏幕上, SET SERVEROUTPUT ON SIZE 200000IT我最牛-程序员的技术讨论与分享园地 [QN1b/S{p EXEC P_LIST_TRANSACTIONS(ORA_SJJK); 其中,存储过程的参数as_destination为所要查看的事务传播到目的节点的延迟队列,为数据库联接(DBLINK)名。假如我们看到一个事务具有很多的调用(超过50个),这个事务很可能就是造成延迟事务队列推过程延迟甚至是挂起的原因。附:存储过程脚本:下载该脚本 CREATE OR REPLACE PROCEDURE REPADMIN.P_LIST_TRANSACTION(as_destination in VARCHAR2) ISIT我最牛-程序员的技术讨论与分享园地.iF8N-]X)] local_node VARCHAR2(128); h}6G.w-Ynvo xm0remote_node VARCHAR2(128); -rt;~'~S5t;H$_0last_scn NUMBER; ]-IYARd!C0last_tid VARCHAR2(22); A(G:f1^/zEg0last_tdb VARCHAR2(128); -k7e1jF8x~%Y2U0cnt NUMBER; CURSOR c(last_delivered NUMBER, last_tid VARCHAR2, last_tdb VARCHAR2) IS %K} iw5^+U0@.p#l_;Y0select cscn, enq_tid, "mfj?wQPR?0dscn, DECODE(c.recipient_key, 0, 'D', 'R')IT我最牛-程序员的技术讨论与分享园地"|T iM&C from system.def$_aqcall c whereIT我最牛-程序员的技术讨论与分享园地 ]7{z(V)Y r (c.cscn >= last_delivered) r3j^ qN(Q dJ0and ((c.cscn > last_delivered) or (c.enq_tid > last_tid))IT我最牛-程序员的技术讨论与分享园地#cM`Sy2|z"J!mkd and (IT我最牛-程序员的技术讨论与分享园地 uGND5w^zK ( c.recipient_key = 0IT我最牛-程序员的技术讨论与分享园地 S9X"R0rr [ and exists ( select /*+ index(cd def$_calldest_primary) */ nullIT我最牛-程序员的技术讨论与分享园地)}6g9X,VW6rSI from system.def$_calldest cd Qu RoT0where cd.enq_tid = c.enq_tid c:|F}H:U8H0and cd.dblink = remote_node ) )IT我最牛-程序员的技术讨论与分享园地o:xlN-\~&RW or ( c.recipient_key > 0 /n.C.U#x+@^r9i0and ( ( exists ( RJn1N X8L0select null from system.repcat$_repprop P p0K"SHo0where P.dblink = remote_node (v/@uPB S#Z+BK0and P.how = 1IT我最牛-程序员的技术讨论与分享园地z8c/d,_dl:k)V z4v c?\)I and P.recipient_key = c.recipient_keyIT我最牛-程序员的技术讨论与分享园地8^#XZ esRGsV7@X and ((P.delivery_order is NULL) J,A8YJF&R.rk7i0or (P.delivery_order < c.cscn))))IT我最牛-程序员的技术讨论与分享园地Q~QMzj2qu or ( existsIT我最牛-程序员的技术讨论与分享园地h0u!g4u`n]Fk ( select /*+ ordered use_nl(rp) */ nullIT我最牛-程序员的技术讨论与分享园地xi7JU%o8k ?rK6^ from system.def$_aqcall cc, system.repcat$_repprop rp ]LI(_ iW*Lq0where cc.enq_tid = c.enq_tidIT我最牛-程序员的技术讨论与分享园地 j L]1po+OO$} and cc.cscn is null DT:w:s K mV%Zi)e-eE0and rp.recipient_key = cc.recipient_key T Sk,Q3Yi0and rp.how = 1IT我最牛-程序员的技术讨论与分享园地#oJ'FE/m:oZ and rp.dblink = remote_node 5Sq cXFi0and ((rp.delivery_order is NULL)IT我最牛-程序员的技术讨论与分享园地W%i]?['Q H"w%c t6R or (rp.delivery_order < c.cscn))))))) )Jz,Z _.v8sKK0order by c.cscn, c.enq_tid; -bX3g%})S0 BEGINIT我最牛-程序员的技术讨论与分享园地cg;O {S;P,C SELECT NLS_UPPER(global_name) INTO local_node FROM global_name;IT我最牛-程序员的技术讨论与分享园地6V*YiVDf1V SELECT dblink INTO remote_node from deftrandest 4rwJ,K)J%T#Vb0WHERE dblink LIKE UPPER (as_destination'%') AND ROWNUM < 2;IT我最牛-程序员的技术讨论与分享园地Ot {l0Y3r IF (remote_node IS NULL) THENIT我最牛-程序员的技术讨论与分享园地 M0?+t&J!i7K7A DBMS_OUTPUT.PUT_LINE ('不能确定目标节点,输入参数有误!');IT我最牛-程序员的技术讨论与分享园地h!OAf1V!p$_%a\ RETURN; J#| ~8K)\(~0ELSEIT我最牛-程序员的技术讨论与分享园地r1TMy#X-ycB A DBMS_OUTPUT.PUT_LINE ('延迟事务目标节点为: 'remote_node); }@3Q4B hX0QNU0DBMS_OUTPUT.PUT_LINE ('-------------------------------------------'); j#O*A.|9l*x't0END IF; ]Zu\p!M;oL0SELECT last_delivered, last_enq_tid, dblink M+},sK&?kTW0yy0INTO last_scn, last_tid, last_tdbIT我最牛-程序员的技术讨论与分享园地 K6p)_&{{.w9j\F'l FROM system.def$_destinationIT我最牛-程序员的技术讨论与分享园地1TReDRJ&S@M WHERE dblink = remote_node; FOR R IN C(last_scn,last_tid,last_tdb) LOOP /d7paN2i0SELECT count(*) INTO cnt FROM system.def$_aqcall WHERE enq_tid = r.enq_tid; 'ZsC8D&i1VPn0DBMS_OUTPUT.PUT_LINE ('延迟事务 ID='r.enq_tid' 调用个数='to_char(cnt)); mCj!Dqr$Y/n#}0END LOOP; rune`K0END; 9yy'z{9dB0/ @5wg:b|6{0 二、Oracle 8高级复制环境设置问题诊断脚本要保证搭建的一个高级复制环境工作,必须保证所有的复制对象处于正常状态,对于一个高级复制环境,要检查一个复制环境中是否所有对象均处于正常工作状态,需要检查不同的系统字典对象,包括复制组对象,复制对象,复制方案对象等等。假如搭建的这个高级复制环境包含很多节点,每个节点又包含几个复制方案(schema)以及每个方案又包含多个复制对象,则完成一遍检查需要作很多的重复工作,这里针对这个问题,编写了一个复制设置问题诊断包,只有运行该包中相应的过程,即可完成对上面提到的相关对象的诊断,给出相应诊断结果。运行方法是,在SQL/PLUS环境下, SQL> spool <文件名>IT我最牛-程序员的技术讨论与分享园地}M(~$p;~+u SQL> set serveroutput on Y'krMK/REE0SQL> exec rep_diag.rep_diag; 这里强调一点,运行该包的用户,必须具有对系统字典表dba_repschema、dba_diagnose、dba_repcat以及dba_repcatlog的检索(select)权限,当然,复制治理员(RepAdmin)用户是均有这些权限的。附:高级复制环境设置问题诊断包脚本。下载该脚本 CREATE OR REPLACE PACKAGE REP_DIAG IS RmHX+AO kyL0PROCEDURE REP_DIAG;IT我最牛-程序员的技术讨论与分享园地} g W'f)wR*`3\4H PROCEDURE REP_SCHEMA;IT我最牛-程序员的技术讨论与分享园地O L][Y'i:h PROCEDURE REP_OBJECT; ?sl|$N)G*W0PROCEDURE REP_ERROR;IT我最牛-程序员的技术讨论与分享园地t(sw~2W%d,O ES3j PROCEDURE REP_STAT;IT我最牛-程序员的技术讨论与分享园地glC a aHf{f END REP_DIAG; 9tosP r2i9iQ0/ CREATE OR REPLACE PACKAGE BODY REP_DIAG IS %}GF'Ll%O3s0PROCEDURE REP_DIAG ISIT我最牛-程序员的技术讨论与分享园地E^B3{9N(z.Q{ BEGINIT我最牛-程序员的技术讨论与分享园地 q\ EDRj0w m REP_SCHEMA;IT我最牛-程序员的技术讨论与分享园地M-H3HX.F{ REP_OBJECT;IT我最牛-程序员的技术讨论与分享园地 s+]'[rz'w REP_ERROR;IT我最牛-程序员的技术讨论与分享园地l0nO9l q#K&L2o REP_STAT; mP"SO\0END REP_DIAG; PROCEDURE REP_SCHEMA ASIT我最牛-程序员的技术讨论与分享园地)\)v7|aZZ CURSOR C_SCHEMA IS SELECT SNAME, DBLINK, MASTERDEFIT我最牛-程序员的技术讨论与分享园地DQ$h#G;g1E:o'Xb FROM SYS.DBA_REPSCHEMA;IT我最牛-程序员的技术讨论与分享园地0zD+A pfcN[7L BEGINIT我最牛-程序员的技术讨论与分享园地Zr)Ci[5ij DBMS_OUTPUT.PUT_LINE('复制方案明细信息');IT我最牛-程序员的技术讨论与分享园地v[!I](f DBMS_OUTPUT.PUT_LINE('-------------------------'); "ly?a a4V P ?W ww z%w0 FOR T_SCHEMA IN C_SCHEMA LOOP (?&A[1uJ W:\/JA2w0 DBMS_OUTPUT.PUT_LINE('方案名称: 'T_SCHEMA.SNAME);IT我最牛-程序员的技术讨论与分享园地V"|+sC ZH6c DBMS_OUTPUT.PUT_LINE('是否为主定义节点: 'T_SCHEMA.MASTERDEF);IT我最牛-程序员的技术讨论与分享园地H9b2r}4U DBMS_OUTPUT.PUT_LINE('数据库联接名称: 'T_SCHEMA.DBLINK);IT我最牛-程序员的技术讨论与分享园地p+D6?J/mxl {(`5\*k DBMS_OUTPUT.PUT_LINE('.');IT我最牛-程序员的技术讨论与分享园地]J,Cp7txXe5` END LOOP; )p@P'v[0END REP_SCHEMA; q5~:i"^ E?f? IN0 PROCEDURE REP_OBJECT AS Q E-|1|bn.z0 CURSOR C_REP_OBJECT IS SELECT SNAME, ONAME, TYPE, STATUSIT我最牛-程序员的技术讨论与分享园地 ?w.KLAU r V@^1m(B
|