免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2114 | 回复: 4
打印 上一主题 下一主题

正在写Oracle高级复制的文档,这里是其中的FAQ部分 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2004-05-05 00:23 |只看该作者 |倒序浏览
希望大家能够提出自己对于高级复制的疑问,
力争作到有问必答


Q:如果高级复制环境中的主体定义站点损坏,如何将主体定义站点切换到另外的主体站点上?
A:分为两种情况。
备注:每次运行完repcat包以后都应该执行一次commit,因为某些rep的存储过程是不会自动commit的,同时这也是一个troubleshooting,一般的rep脚本都会较快的返回结果,如果一条命令之后长时间没有结果返回,那么很可能是上面的命令没有commit,取消掉当前的命令,然后作一次commit,再重新执行,一般都能够解决问题。
一是只有主体定义站点损坏。假设站点A是主体定义站点,已经损坏,在复制环境中还有站点B,想作为新的主体定义站点。
1.以repadmin身份登录站点B,执行主体站点切换。
connect repadmin/repadmin
execute dbms_repcat.relocate_masterdef  
(gname =>; 'groupname',  
old_masterdef =>; 'oldmaster.world',  
new_masterdef =>; 'newmaster.world',   
notify_masters =>; true,  
include_old_masterdef =>; false);

2.将站点A作为主体站点删除
execute dbms_repcat.remove_master_databases  
(gname =>; 'groupname',  
master_list =>; 'oldmasterdef.world');

3.当站点A重新可用时,用repadmin用户登录站点A,删除其中的复制组信息
connect repadmin/repadmin               
execute dbms_repcat.drop_master_repgroup  
(gname =>; 'groupname',  
drop_contents =>; true,  
all_sites =>; false);

如果要使站点A重新称为复制环境中的一个主体站点,继续执行下面的4,5两步,否则切换主体定义站点就已经完成了。
4. 登录站点B(新的主体定义站点)
connect repadmin/repadmin
  
execute dbms_repcat.suspend_master_activity  
(gname =>; 'groupname')  
  
execute dbms_repcat.add_master_database  
(gname =>; 'groupname',  
master =>; 'oldmasterdef.world',  
use_existing_objects =>; true,  
copy_rows =>; false);  

5.重新开始复制
execute dbms_repcat.resume_master_activity  
(gname =>; 'groupname')

第二种情况是一些主体站点和主体定义站点同时损坏了。
1.依次登录所有正常运行的主体站点,执行主体定义站点切换
execute dbms_repcat.relocate_masterdef  
(sname =>; 'schemaname',  
old_masterdef =>; 'oldmaster.world',  
new_masterdef =>; 'newmaster.world',   
notify_masters =>; false,  /*此处是false,而第一种情况中这个参数是true */
include_old_masterdef =>; false);

后面的操作步骤跟情况一相同,依次执行2-5就可以了。

论坛徽章:
0
2 [报告]
发表于 2004-05-05 00:24 |只看该作者

正在写Oracle高级复制的文档,这里是其中的FAQ部分

Q:如何计算延迟事务将占用多少的资源?
A:Deferred Transactions
Oracle forwards data replication information by propagating (that is, sending and executing) the RPCs that are generated by the internal triggers described previously. These RPCs are stored in the deferred transaction queue. In addition to containing the execution command for the internal procedure at the destination site, each RPC also contains the data to be replicated to the target site. Oracle uses distributed transaction protocols to protect global database integrity automatically and ensure data survivability.
Deferred Transaction Queue
This queue stores the transactions (for example, DML) that are bound for another destination in the master group. Oracle stores RPCs produced by the internal triggers in the deferred transaction queue of a site for later propagation. Oracle also records information about initiating transactions so that all RPCs from a transaction can be propagated and applied remotely as a transaction. Oracle's replication facility implements the deferred transaction queue using Oracle's advanced queuing mechanism.
上面是Oracle联机文档中对于延迟事务和延迟事务队列的描述。
开始的时候一直以为延迟事务应该是存在Oracle的一个内存结构中,所以总是担心如果复制环境中的网络长时间出现问题,那么会不会导致延迟事务队列占用大量的内存而使数据库的其它操作变慢,或者说超出了延迟事务可以使用的内存大小而产生错误。
因为上面提到延迟事务队列使用的是Oracle的高级队列(Advanced Queue)算法,所以又查找了高级队列的文档,发现多处提到Table这个词,所以忽然明白所谓延迟事务的队列应该是存储在磁盘上的某些表中,这样陡然就解决了心中很多疑问,首先事务多只是占用硬盘空间,其次要想计算事务占用的资源可以通过表的block数来计算。
于是通过SQL Trace,找到了延迟事务相关视图的基表。
deftran对应DEF$_AQCALL表,通过执行计划也发现在统计大量延迟事务总数时候速度极为缓慢的原因,因为在作TABLE ACCESS FULL DEF$_AQCALL,同时还会作TABLE ACCESS FULL DEF$_AQERROR,还有UNION ALL的操作。
deferror对应DEF$_ERROR表。defcall对应的也是DEF$_AQCALL和DEF$_AQERROR表。
现在我们检查一下DEF$_AQCALL表的信息。
SQL>; col owner for a10
SQL>; col object_name for a20
SQL>; select owner,object_name,object_id,data_object_id,object_type from dba_objects where object_name='DEF$_AQCALL';

OWNER      OBJECT_NAME           OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE
---------- -------------------- ---------- -------------- ------------------
SYS        DEF$_AQCALL                3913                SYNONYM
SYSTEM     DEF$_AQCALL                3861           3861 TABLE
SYSTEM     DEF$_AQCALL                3869                QUEUE

Executed in 0.06 seconds

从上面的结果可以看到这个表是属于SYSTEM的,在SYS下有一个同义词。
再检查一下segment的情况,我们可以从dba_segments或者dba_extents视图中查看。
SQL>; col tablespace_name for a20
SQL>; select owner,tablespace_name,bytes,blocks from dba_segments where segment_name='DEF$_AQCALL';

OWNER      TABLESPACE_NAME           BYTES     BLOCKS
---------- -------------------- ---------- ----------
SYSTEM     SYSTEM                    65536          8

Executed in 0.11 seconds

由此我们已经可以知道作为高级复制中延迟事务存储所占用的资源,同时由于这是普通的表,那么当插入记录的时候当然也是会缓存在buffer cache中。这里不作讨论。
也不再讨论DEF$_AQERROR表,因为只有在延迟事务产生错误时才会插入,如果高级复制环境中没有太多错误,这个表的资源占用可以不考虑。

为了继续验证,现在测试环境中有REP_HOME复制组,其中的复制对象是SCOTT.EMP_2003表。断开网络连接的情况下,我们插入10000条记录。
再次检索DEF$_AQCALL表现在的情况。
SQL>; select owner,tablespace_name,bytes,blocks from dba_segments where segment_name='DEF$_AQCALL';

OWNER      TABLESPACE_NAME           BYTES     BLOCKS
---------- -------------------- ---------- ----------
SYSTEM     SYSTEM                  2097152        256

Executed in 0.08 seconds

现在该表的大小已经扩大到2M,可以认为所有的复制数据和队列信息都存储在这张表中。

SQL>; select count(*) from DEF$_AQCALL;

  COUNT(*)
----------
     10000

Executed in 0.04 seconds

再次证明确实是10000条数据。

如果此时我们用repadmin用户检索defcall和deftran视图
SQL>; select count(*) from defcall;

  COUNT(*)
----------
     10000

已用时间:  00: 00: 02.04

SQL>; select count(*) from deftran;

  COUNT(*)
----------
         1

已用时间:  00: 00: 00.00

可以看到deftran视图中只有一条记录,因为上面的10000条数据的插入是一个事务中完成的,所以在复制环境中作为一个延迟事务处理。
而defcall中则是10000条记录,详细查看内容,知道所有的cal事务号都相同,而callno不同,同时我们发现直接检索DEF$_AQCALL只需要0.04秒,而检索defcall视图却需要2秒,所以如果想要计算到底有多少数据需要处理的时候,我们可以直接从DEF$_AQCALL检索,这样可以缩短查询时间。

论坛徽章:
0
3 [报告]
发表于 2004-05-05 00:24 |只看该作者

正在写Oracle高级复制的文档,这里是其中的FAQ部分

Q:如何检查一个错误的延迟事务到底作了什么?
A:有些时候因为种种原因,可能复制操作会出现错误。检查DEFERROR视图会发现有错误的延迟事务,我们首先可以通过DEFERRED_TRAN_ID和CALLNO在DEFCALL视图中查询这个操作大体上是在干什么。
SQL>; select schemaname, packagename, procname from defcall;

SCHEMANAME                     PACKAGENAME                    PROCNAME
------------------------------                 ------------------------------                 ------------------------------
SCOTT                          EMP_2003$RP                    REP_DELETE
SCOTT                          EMP_2003$RP                    REP_DELETE

Executed in 0.06 seconds

其中SCHEMANAME表示哪个用户执行的DML,PACKAGENAME中可以知道是哪个对象上的操作,PROCNAME则可以知道是插入,更新还是删除。
但是这样的信息往往不足够我们判断问题。我们想知道到底这个SQL干了什么,怎么办?
我们可以利用DBMS_DEFER_QUERY.GET_CALL_ARGS来达到目的。
运行以下的存储过程,可以得到想要查询的延迟事务的具体参数值。
    CREATE OR REPLACE PROCEDURE GET_CALL(tran_id  IN STRING,
                      callno   IN NUMBER,
                      startarg IN NUMBER := 1,
                      argcnt   IN NUMBER,
                      argsize  IN NUMBER,
                      tran_db  IN STRING := '') IS
        v_types     DBMS_DEFER_QUERY.TYPE_ARY;
        v_vals      DBMS_DEFER_QUERY.VAL_ARY;
        indx        NUMBER;
        v_type_desc VARCHAR2(50);
    BEGIN
        DBMS_DEFER_QUERY.GET_CALL_ARGS(callno   =>; callno,
                                       startarg =>; startarg,
                                       argcnt   =>; argcnt,
                                       argsize  =>; argsize,
                                       tran_db  =>; tran_db,
                                       tran_id  =>; tran_id,
                                       date_fmt =>; 'YYYY-MM-DD HH24:MI:SS',
                                       types    =>; v_types,
                                       vals     =>; v_vals);
   
        FOR indx IN 1 .. argcnt LOOP
            IF v_types(indx) = 1 THEN
                v_type_desc := 'VARCHAR2';
            END IF;
            IF v_types(indx) = 2 THEN
                v_type_desc := 'NUMBER';
            END IF;
            IF v_types(indx) = 12 THEN
                v_type_desc := 'DATE';
            END IF;
            IF v_types(indx) = 23 THEN
                v_type_desc := 'RAW';
            END IF;
            IF v_types(indx) = 96 THEN
                v_type_desc := 'CHAR';
            END IF;
            IF v_types(indx) = 11 THEN
                v_type_desc := 'ROWID';
            END IF;                        
            dbms_output.put_line('Arg ' || indx || ': Datatype ' ||
                                 v_type_desc || '; Value: ' ||
                                 v_vals(indx));
        END LOOP;
END GET_CALL;

另外我们可以通过查询DEF$_AQCALL 表的USER_DATA字段也可以得到数据,这是一个BLOB字段,提取BLOB字段内容的方法这里不再讨论,如果有兴趣的可以自己试一下。

论坛徽章:
0
4 [报告]
发表于 2004-05-05 00:25 |只看该作者

正在写Oracle高级复制的文档,这里是其中的FAQ部分

Q:如果一张表没有主键,又确实需要复制,怎么办?
A:不建议在高级复制的环境中出现这样的情况,应该确保每张表都有主键。如果确实存在这种情况,那么需要用DBMS_REPCAT.SET_COLUMNS来生成代用主键。
execute DBMS_REPCAT.SET_COLUMNS(sname =>; test', oname =>; 'tabel', column_list =>; 'col1,col2,col3,col4');
其中column_list是用逗号隔开的字段列表,不能有空格。
注意:不要在执行set_columns之前生成对于没有主键的对象的复制支持,也就是不要运行generate_replication_support,否则会导致all_repobject视图中该对象状态变为ERROR,而无法再次set_columns。
如果误运行了复制支持而又没有成功,那么需要删除掉这个复制对象再重新生成。
也就是在对没有主键的表生成复制的时候,必须遵循以下顺序:
create_master_repobject ->; set_columns ->; generate_replication_support

论坛徽章:
0
5 [报告]
发表于 2004-05-05 00:25 |只看该作者

正在写Oracle高级复制的文档,这里是其中的FAQ部分

Q:高级复制环境中出现长时间的网络问题会出现什么情况?
A:由于高级复制的传播都是通过JOB来实现的,而大家知道Oracle对于JOB的执行有个限制,就是如果一个JOB执行失败了16次,那么这个JOB将会被标志为BROKEN,以后这个JOB再也不会被自动执行,除非是手动设置BROKEN为FALSE或者手动成功地运行一次JOB。
这个特性给我们的实际应用中带来了一些麻烦,假设我们的PUSH JOB定义的时间间隔是一分钟,那么如果主体站点之间的网络出现长时间的问题,比如说超过了16分钟,也就是此时JOB已经失败了16次,那么PUSH的JOB就被标志为BROKEN了,这样等到网络问题修复,会发现堆积的延迟事务也不会被PUSH到其它的主体站点上。
如果不注意这个问题,往往就会出现严重的问题。
解决方案是另外作一个JOB,这个JOB里面每隔一定时间自动检查那个PUSH JOB的状态,如果是BROKEN的,那么自动将其BROKEN状态重新设置为FALSE,这样下次又可以重新执行了。
这个JOB中执行的存储过程基本上如下:
DECLARE
    CURSOR my_broken_jobs IS
        SELECT job FROM user_jobs WHERE broken = 'Y';
BEGIN
    FOR broken_job IN my_broken_jobs LOOP
        BEGIN
            dbms_job.broken(broken_job.job, FALSE);
        EXCEPTION
            WHEN OTHERS THEN
                NULL;
        END;
    END LOOP;
END;
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP