用于Oracle容灾和RAC的测试代码

         因为工作关系,在测试一些软件或演示时,需要一段能很清楚的演示容灾和RAC的自动切换效果的代码.发现达到满意的效果还是有些技巧的. DBMS_OUTPUT并不能实时的反应出效果.而Oracle的管道反而正合用,所以后面整理了下.效果还比较满意.

效果如下:



1. 定义一个用于返回运行状态的自定义类型
  --定义类型
CREATE OR REPLACE TYPE  obj_tab_demo AS OBJECT (
id number,
timesta TIMESTAMP(6) WITH TIME ZONE,
 inst       VARCHAR2(16),
 insthost VARCHAR2(64)
);
 --实例化
CREATE OR REPLACE TYPE  o_tab_demo  AS TABLE OF  obj_tab_demo ; 
  小技巧:
    如果你已经执行了,想重建会报 ORA-02303 错误,11g虽有个force,并不好用.删除重建好了.
drop type  o_tab_demo   
drop type  obj_tab_demo  
要注意,此时用到这个类型的相关对象状态是失效的.
2. 创建存储过程
  -- 相关知识:
  -- Oracle管道化表函数 可以返回整个行的集.
  -- 管道化表函数必须返回一个集合,在函数中,PIPE ROW语句 被用来返回该集合
   --的个元素,此函数必须以一个空的RETURN语句结束,以表明它已经完成.
CREATE OR REPLACE FUNCTION fun_demo(p_num NUMBER)
RETURN o_tab_demo
PIPELINED
IS
  v_instname varchar2(16);
  v_hostname  varchar2(64);
  v_obj obj_tab_demo;
BEGIN
   FOR i in 1 ..p_num LOOP
    --实例序号
   v_inst := userenv('instance');
   -- 主机名
   v_hostname   := sys_context('userenv','host') ;
     -- 可以从v$instance视图中找,也可按上面的方法找出
     -- SELECT instance_name,host_name into v_instname,v_hostname FROM v$instance;
      v_obj := obj_tab_demo(i,systimestamp,v_instname, v_hostname  ); --systimestamp
      PIPE ROW(v_obj);
    END LOOP;
    RETURN;
EXCEPTION
WHEN OTHERS THEN
     DBMS_OUTPUT.PUT_LINE(SQLCODE||' '||SUBSTR(SQLERRM,1,200));
END;
       --附注:
        -- 如果想保存结果或要求测试INSERT,可以创建一个DEMO表,关在函数中将序号,时间和当前实例都存进去,需要用自治事务处理.
--DEMO表结构 :
create table demo
(
  id number,
  timesta TIMESTAMP(6) WITH TIME ZONE,
  inst VARCHAR2(16),
  insthost VARCHAR2(64)
)
3. 在PL/SQL Developer或SQLPlus中运行测试    
    a. 得到当前session ID,用处在于,你输入的循环值太大,手工中断时会用到.
       SELECT DISTINCT(SID) INTO v_sessionsid FROM V$MYSTAT;      
    b. 打开output和运行时间开关
        set serveroutput on
        set timing on
    c.  在SQL查询中使用TABLE操作符来使Oracle函数返回Table集合   
        col  id for a8
        col  inst  for a10
        col  timesta  for a40
        col  insthost  for a10
        SELECT * FROM TABLE( fun_demo(10000) );
 4. 如果你认为你已达到测试目地,就可以强行中止未运行完的SELECT了.
        如放在工具中执行,很简单,直接在菜单中选择相关项中止即可.
        如需手工方式中止,按下面的方法:
        a.找出会话ID和序列号,并得到kill命令         
 select s.username, s.osuser,
     s.sid, s.serial#,
     p.spid, s.program,
     s.STATUS,
     'alter system kill session '||''''||s.sid||','||s.serial#||',@1'';' as oracle_kill
     from v$session s,v$process p
    where s.paddr = p.addr and s.username is not null         
      and s.sid = 上面查出的session id;
  b.然后运行  oracle_kill  杀掉会话即可.
5. 统计时间误差,看切换时间.这个是重点
    找出上面实时输出的时间点,找到所要的切换时间点,分别给time1和time2 变量.
    再运行下面代码,得到时间差.
    代码:
DECLARE
 v_time1 TIMESTAMP(6) WITH TIME ZONE;
 v_time2 TIMESTAMP(6) WITH TIME ZONE;
 v_seconds NUMBER;
 v_minutes NUMBER;
 v_hours NUMBER;
 v_days NUMBER;
 v_weeks NUMBER;
BEGIN
 v_time1 := '13-12月-13 10.22.31.765000 上午 +08:00';
 v_time2 := '13-12月-13 10.23.04.546000 上午 +08:00';
SELECT substr((v_time2-v_time1),instr((v_time2-v_time1),' ')+7,2) seconds,
       substr((v_time2-v_time1),instr((v_time2-v_time1),' ')+4,2) minutes,
       substr((v_time2-v_time1),instr((v_time2-v_time1),' ')+1,2) hours,
       trunc(to_number(substr((v_time2-v_time1),1,instr(v_time2-v_time1,' '))))  days,
       trunc(to_number(substr((v_time2-v_time1),1,instr(v_time2-v_time1,' ')))/7) weeks
  INTO v_seconds,v_minutes,v_hours,v_days,v_weeks
  FROM dual;
  DBMS_OUTPUT.PUT_LINE('-------------------------------------------------');
  DBMS_OUTPUT.PUT_LINE('begin: '||v_time1);
  DBMS_OUTPUT.PUT_LINE('end : '||v_time2);
  DBMS_OUTPUT.PUT_LINE('-------------------------------------------------');
  DBMS_OUTPUT.PUT_LINE('seconds : '||v_seconds);
  DBMS_OUTPUT.PUT_LINE('minutes : '||v_minutes);
  DBMS_OUTPUT.PUT_LINE('hours : '||v_hours);
  DBMS_OUTPUT.PUT_LINE('days : '||v_days);
  DBMS_OUTPUT.PUT_LINE('weeks : '||v_weeks);
  DBMS_OUTPUT.PUT_LINE('-------------------------------------------------');
EXCEPTION
WHEN OTHERS THEN
     DBMS_OUTPUT.PUT_LINE(SQLCODE||' '||SUBSTR(SQLERRM,1,200));
END;
/

至此,应当就能得到想要的效果了。

MAIL:xcl_168@aliyun.com

Blog:http://blog.csdn.net/xcl168

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值