为什么在使用DMBS_STREAMS_ADM.MAINATIAN_TABLES过程时不在目标数据库中创建表?

时间:2014-02-24 18:49:00

标签: database-replication datapump oracle-streams

我正在实现一个Oracle Streams环境,它可以在某些表上复制DML更改。

我使用过程 DBMS_STREAMS_ADM.MAINTAIN_TABLES ,并将实例化为DBMS_STREAMS_ADM.INSTANTIATION_TABLE_NETWORK,过程的所有块都成功执行,但是这些表并未在目标数据库中创建。

docs中所述:

  

如果此参数设置为DBMS_STREAMS_ADM.INSTANTIATION_TABLE或DBMS_STREAMS_ADM.INSTANTIATION_TABLE_NETWORK,则实例化的表必须存在于源数据库中,并且包含这些表的表空间必须存在于目标数据库中。

详细信息:

  1. 存在从目标数据库到源数据库的数据库链接。

  2. 表存在于源数据库中,表空间也存在于目标数据库中。

  3. 目标数据库中的用户SCOTT 不存在

  4. 源数据库是Oracle Database 11g企业版11.2.0.3.0版 - 64位生产

  5. 目标数据库是Oracle Database 11g Express Edition版本11.2.0.2.0 - 生产

  6. 主要代码:

    DECLARE
      tables DBMS_UTILITY.UNCL_ARRAY;
      i      number := 1;
      j      number := 1;
      iscn  NUMBER;
    
    BEGIN
    
      FOR c IN (select table_name from config_tables) LOOP
        tables(i) := c.table_name;
        i := i + 1;
      END LOOP;
    
      DBMS_STREAMS_ADM.MAINTAIN_TABLES(table_names                  => tables,
                                       source_directory_object      => NULL,
                                       destination_directory_object => NULL,
                                       source_database              => 'db1_global_name',
                                       destination_database         => 'db2_global_name',
                                       perform_actions              => TRUE,
                                       capture_name       => 'DML_Capture_Src',
                                       capture_queue_name => 'strmadmin.dml_streams_queue',
                                       propagation_name   => 'DML_Propagation',
                                       apply_name         => 'DML_Apply_Dest',
                                       apply_queue_name   => 'strmadmin.dml_streams_queue',
    
                                       bi_directional => FALSE,
                                       include_ddl    => FALSE,
                                       instantiation  => DBMS_STREAMS_ADM.INSTANTIATION_TABLE_NETWORK);
    END;
    /
    

    代码生成14个块,第7个块(使用数据泵)

    -- 
    -- Datapump TABLE MODE IMPORT (NETWORK)
    -- 
    DECLARE
      h1                NUMBER := NULL; -- data pump job handle
      name_expr_list    VARCHAR2(32767); -- for metadata_filter
      object_name       dbms_utility.uncl_array; -- object names
      cnt               NUMBER;
      object_owner      VARCHAR2(30); -- owner
      job_state         VARCHAR2(30); -- job state
      status            ku$_Status; -- data pump status
      job_not_exist     exception;
      pragma            exception_init(job_not_exist, -31626);
      local_compat            v$parameter.value%TYPE;
      remote_compat            v$parameter.value%TYPE;
      min_compat            v$parameter.value%TYPE;
      ind               NUMBER; 
      le                ku$_LogEntry;  -- For WIP and error messages
      js                ku$_JobStatus; -- The job status from get_status 
      jd                ku$_JobDesc; 
    -- The job description from get_status
    BEGIN
    
      object_name(1) := 'DEPT';
      object_name(2) := 'SALGRADE';
      object_owner := 'SCOTT';
      FOR idx IN 1..2 LOOP
        SELECT COUNT(1) INTO cnt FROM all_tables@"db2_global_name"
          WHERE owner = object_owner AND table_name = object_name(idx);
        -- table does not exist locally, need instantiation
        IF cnt = 0 THEN
          IF name_expr_list IS NULL THEN
            name_expr_list := '(';
          ELSE
            name_expr_list := name_expr_list ||',';
          END IF;
          name_expr_list := name_expr_list||''''||object_name(idx)||'''';
        END IF;
      END LOOP;
      IF name_expr_list IS NOT NULL THEN
        name_expr_list := name_expr_list || ')';
      ELSE
        COMMIT;
        RETURN;
      END IF;
    
      select value into local_compat from v$parameter@"db1_global_name"
      where name = 'compatible';
      select value into remote_compat from v$parameter@"db2_global_name"
      where name = 'compatible';
      IF TO_NUMBER(REPLACE(local_compat, '.', '0')) > TO_NUMBER(REPLACE(remote_compat, '.', '0')) THEN
        min_compat := remote_compat;
      ELSE
        min_compat := local_compat;
      END IF;
      h1 := dbms_datapump.open(operation=>'IMPORT',job_mode=>'TABLE',
        remote_link=>'db1_global_name',
        job_name=>NULL, version=> min_compat);
    
    
    
      dbms_datapump.metadata_filter(
        handle=>h1,
        name=>'NAME_EXPR',
        value=>'IN'||name_expr_list);
      dbms_datapump.metadata_filter(
        handle=>h1,
        name=>'SCHEMA_EXPR',
        value=>'IN'||'(''SCOTT'')');
    
      dbms_datapump.start_job(h1);
    
      job_state := 'UNDEFINED';
      BEGIN
        WHILE (job_state != 'COMPLETED') AND (job_state != 'STOPPED') LOOP
          status := dbms_datapump.get_status(
            handle => h1,
            mask => dbms_datapump.ku$_status_job_error +
                    dbms_datapump.ku$_status_job_status +
                    dbms_datapump.ku$_status_wip,
            timeout => -1);
          job_state := status.job_status.state;
          dbms_lock.sleep(10);
        END LOOP;
      EXCEPTION WHEN job_not_exist THEN
        dbms_output.put_line('job finished');
      END;
      COMMIT;
    EXCEPTION WHEN OTHERS THEN
      dbms_output.put_line('Exception, sql code = ' || SQLCODE || ', error message: ' || SQLERRM);
      dbms_output.put_line( dbms_utility.format_error_stack);
      dbms_output.put_line( dbms_utility.format_error_backtrace);
    
      IF h1 IS NOT NULL THEN 
        BEGIN 
          dbms_datapump.get_status( 
            handle    => h1, 
            mask      => dbms_datapump.ku$_status_job_error + 
                         dbms_datapump.ku$_status_job_status +
                         dbms_datapump.ku$_status_wip, 
            timeout   => -1, 
            job_state => job_state,
            status     => status );
    
          dbms_output.put_line('Data pump job status: ' || job_state);
          le := status.wip; 
          IF le IS NULL THEN 
            dbms_output.put_line('WIP info is NULL'); 
          ELSE 
            dbms_output.put_line('WIP info:'); 
            ind := le.FIRST; 
            WHILE ind IS NOT NULL LOOP 
              dbms_output.put_line(le(ind).LogText); 
              ind := le.NEXT(ind); 
            END LOOP; 
          END IF; 
    
          le := status.error; 
          IF le IS NULL THEN 
            dbms_output.put_line('Error info is NULL'); 
          ELSE 
            dbms_output.put_line('Error info:'); 
            ind := le.FIRST; 
            WHILE ind IS NOT NULL LOOP 
              dbms_output.put_line(le(ind).LogText); 
              ind := le.NEXT(ind); 
            END LOOP; 
          END IF; 
        EXCEPTION  
          WHEN job_not_exist THEN 
            dbms_output.put_line('Data pump job finished');
          WHEN OTHERS THEN RAISE; 
        END; 
      END IF; 
      ROLLBACK;
      RAISE;
    END;
    

0 个答案:

没有答案