Pages

Sunday, April 29, 2018

PL/SQ and sqlplus batch by example. Delete from Table in Three Steps

=======================
General
=======================
Generic delete from  a table using Business Logic.
Several million of records are being deleted.
The flow is a three steps process:


Step1.
pre_run_steps.sh
This create backup table for SOURCE_DATA_SUBSCRIBER (SOURCE_DATA_SUBSCRIBER_BAK) 
Creates additional temporary tables which are to be used during actual delete step.


Step2.
main_delete.sh 
The actual DELETE. 
Create the PL/SQL Package, which handles the business logic.
Call the PL/SQL package.
Progress is logged into SGA_W_LOG Table.

Step3.

post_run_steps.sh
This drop the SOURCE_DATA_SUBSCRIBER_BAK and drop additional temporary tables created in pre_run_steps.sh

=======================
Code
=======================
Step 0.
set_vipuser.sql

Step1.
pre_run_steps.sh
pre_run_steps.batpre_run_steps.sql


Step2.
main_delete.shmain_delete.bat
main_delete.sql
MULTI_DELETE.sql

Step3.
post_run_steps.shpost_run_steps.batpost_run_steps.sql

Step 0.
set_vipuser.sql
--Set the connection detailsdefine vipuser=my_userdefine vippass=my_passdefine connectStr=MY_INSTANCE
Step 1.
pre_run_steps.sh
sqlplus /nolog @pre_run_steps.sql

pre_run_steps.bat
sqlplus /nolog @pre_run_steps.sql

pre_run_steps.sql
@../set_vipuser.sql

SET SERVEROUT ON
SET HEADING OFF
SET LINESIZE 400
SET PAGESIZE 0
SET FEEDBACK OFF
SET VERIFY OFF

PROMPT conn &&vipuser/&&vippass@&&connectStr
conn &&vipuser/&&vippass@&&connectStr

EXEC DBMS_OUTPUT.ENABLE(100000);

PROMPT CREATE TABLE SOURCE_DATA_SUBSCRIBER_BAK AS SELECT * FROM SOURCE_USER.SOURCE_DATA_SUBSCRIBER WHERE 1=2;
DECLARE
  v_sql_str    VARCHAR2(2000);
  v_counter    NUMBER;
BEGIN
  SELECT COUNT(*) INTO v_counter FROM USER_TABLES WHERE table_name = 'SOURCE_DATA_SUBSCRIBER_BAK'; 
  IF v_counter = 0 THEN
    v_sql_str := 'CREATE TABLE SOURCE_DATA_SUBSCRIBER_BAK AS SELECT * FROM SOURCE_USER.SOURCE_DATA_SUBSCRIBER WHERE 1=2';
  ELSE
    v_sql_str := 'TRUNCATE TABLE SOURCE_DATA_SUBSCRIBER_BAK';
  END IF;
  EXECUTE IMMEDIATE v_sql_str;
END;
/

PROMPT ALTER TABLE SOURCE_DATA_SUBSCRIBER_BAK MOVE TABLESPACE IGT_TEMP_TABLE;
ALTER TABLE SOURCE_DATA_SUBSCRIBER_BAK MOVE TABLESPACE IGT_TEMP_TABLE;

PROMPT INSERT /*+ APPEND */ INTO SOURCE_DATA_SUBSCRIBER_BAK SELECT * FROM SOURCE_USER.SOURCE_DATA_SUBSCRIBER;
INSERT /*+ APPEND */ INTO SOURCE_DATA_SUBSCRIBER_BAK SELECT * FROM SOURCE_USER.SOURCE_DATA_SUBSCRIBER;
COMMIT;

PROMPT CREATE TABLE   SGA_LOC_GRP_OUTBACK_NETWORKS
DECLARE
  v_sql_str    VARCHAR2(2000);
  v_counter    NUMBER;
BEGIN
  SELECT COUNT(*) INTO v_counter FROM USER_TABLES WHERE table_name = 'SGA_LOC_GRP_OUTBACK_NETWORKS'; 
  IF v_counter = 0 THEN
    v_sql_str := 'CREATE TABLE   SGA_LOC_GRP_OUTBACK_NETWORKS (network_id        NUMBER(10) ) TABLESPACE IGT_TEMP_TABLE;';
  ELSE
    v_sql_str := 'TRUNCATE TABLE SGA_LOC_GRP_OUTBACK_NETWORKS';
  END IF;
  EXECUTE IMMEDIATE v_sql_str;
END;
/


PROMPT CREATE TABLE   MSISDN_PROFILE_NOT_PRE
DECLARE
  v_sql_str    VARCHAR2(2000);
  v_counter    NUMBER;
BEGIN
  SELECT COUNT(*) INTO v_counter FROM USER_TABLES WHERE table_name = 'MSISDN_PROFILE_NOT_PRE'; 
  IF v_counter = 0 THEN
    v_sql_str := 'CREATE TABLE   MSISDN_PROFILE_NOT_PRE (msisdn VARCHAR2(30) NOT NULL) TABLESPACE IGT_TEMP_TABLE;';
  ELSE
    v_sql_str := 'TRUNCATE TABLE MSISDN_PROFILE_NOT_PRE';
  END IF;
  EXECUTE IMMEDIATE v_sql_str;
END;
/

PROMPT INSERT /*+ APPEND */ INTO SGA_LOC_GRP_OUTBACK_NETWORKS
INSERT /*+ APPEND */ INTO SGA_LOC_GRP_OUTBACK_NETWORKS
SELECT DISTINCT network_id 
    FROM SOURCE_USER.SGA_LOCATION_GROUP_ENTRIES 
   WHERE location_group_id IN 
         (SELECT location_group_id 
    FROM SOURCE_USER.SGA_LOCATION_GROUPS 
WHERE LOCATION_GROUP_NAME='Outback');
commit;

PROMPT INSERT /*+ APPEND */ INTO MSISDN_PROFILE_NOT_PRE(msisdn)
INSERT /*+ APPEND */ INTO MSISDN_PROFILE_NOT_PRE(msisdn)
SELECT KEY1 FROM SOURCE_USER.SFI_CUSTOMER_PROFILE WHERE ATTR1 NOT IN ('RogEngPre','RogFrPre','FidoEngPre','FidoFrPre');
commit;


PROMPT CREATE INDEX SFI_CST_PROF_IX
DECLARE
  v_sql_str    VARCHAR2(2000);
  v_counter    NUMBER;
BEGIN
  SELECT COUNT(*) INTO v_counter FROM USER_INDEXES WHERE index_name = 'SFI_CST_PROF_IX'; 
  IF v_counter > 0 THEN
    v_sql_str := 'DROP INDEX SFI_CST_PROF_IX';
  END IF;
  EXECUTE IMMEDIATE v_sql_str;
END;
/

PROMPT CREATE INDEX SFI_CST_PROF_IX ON MSISDN_PROFILE_NOT_PRE(msisdn) TABLESPACE IGT_TEMP_INDEX;
CREATE INDEX SFI_CST_PROF_IX ON MSISDN_PROFILE_NOT_PRE(msisdn) TABLESPACE IGT_TEMP_INDEX;

BEGIN
  DBMS_STATS.gather_table_stats('&&vipuser','MSISDN_PROFILE_NOT_PRE');
END;
/

PROMPT Finished Pre Run step
EXIT;



Step 2.
main_delete.sh
sqlplus /nolog @main_delete.sql

main_delete.bat
sqlplus /nolog @main_delete.sql

main_delete.sql
@../set_vipuser.sql

SET SERVEROUT ON
SET HEADING OFF
SET LINESIZE 400
SET PAGESIZE 0
SET FEEDBACK OFF

PROMPT conn &&vipuser/&&vippass@&&connectStr
conn &&vipuser/&&vippass@&&connectStr

EXEC DBMS_OUTPUT.ENABLE(100000);

PROMPT CREATE PROCEDURE MULTI_DELETE
@MULTI_DELETE.sql

PROMPT EXECUTE PROCEDURE MULTI_DELETE
PROMPT .............................
PROMPT Running DELETE....
PROMPT Follow Up on process Progress by: SELECT * FROM SGA_W_LOG ORDER BY TS_LAST_MODIFIED;
PROMPT .............................

BEGIN
  MULTI_DELETE;
END;
/

PROMPT Finished Run step  
EXIT;


MULTI_DELETE.sql
CREATE OR REPLACE PROCEDURE MULTI_DELETE IS

    v_effected_rows NUMBER;
    v_delete_rows NUMBER;
    v_row_counter NUMBER;
    v_table_name VARCHAR2(30);
    v_sql_str VARCHAR2(1000);
    v_module_name VARCHAR2(30);
    v_msg_text VARCHAR2(1000);

  BEGIN
    v_table_name :='SOURCE_DATA_SUBSCRIBER';
    v_effected_rows := 1;
    v_row_counter := 0;
    v_module_name := 'MULTI DELETE';

    v_sql_str := 'DELETE FROM SOURCE_DATA_SUBSCRIBER WHERE current_network_id NOT IN ( SELECT network_id FROM SGA_LOC_GRP_OUTBACK_NETWORKS ) AND msisdn IN( SELECT msisdn FROM MSISDN_PROFILE_NOT_PRE) AND ROWNUM < 100001';
    v_msg_text  := 'Running SQL: '||v_sql_str;

    INSERT INTO SGA_W_LOG (  procedure_name,  data,  ts_last_modified)
    VALUES(v_module_name,v_msg_text, SYSDATE);
    COMMIT;

    v_msg_text  := 'Starting at: '||TO_CHAR(SYSDATE,'YYYYMMDD hh24:mi:ss');
    INSERT INTO SGA_W_LOG (  procedure_name,  data,  ts_last_modified)
    VALUES(v_module_name,v_msg_text, SYSDATE);
    COMMIT;


    WHILE v_effected_rows > 0 LOOP

      DELETE FROM SOURCE_DATA_SUBSCRIBER
       WHERE current_network_id NOT IN ( SELECT network_id FROM SGA_LOC_GRP_OUTBACK_NETWORKS )
         AND msisdn IN( SELECT msisdn FROM MSISDN_PROFILE_NOT_PRE)
         AND ROWNUM < 100001;


      v_effected_rows := SQL%ROWCOUNT;
      v_row_counter := v_row_counter + v_effected_rows;
      COMMIT;
      
      v_msg_text := v_row_counter||' rows deleted from table '||v_table_name;      
      INSERT INTO SGA_W_LOG (  procedure_name,  data,  ts_last_modified)
      VALUES(v_module_name,v_msg_text, SYSDATE);
      COMMIT;
      
    END LOOP;
    
    COMMIT;
    
    v_msg_text := 'MANUAL_DELETE FROM '||v_table_name||' Finished Successfully';
    INSERT INTO SGA_W_LOG (  procedure_name,  data,  ts_last_modified)
    VALUES(v_module_name,v_msg_text, SYSDATE);
    COMMIT;


  EXCEPTION

    WHEN OTHERS THEN
      v_msg_text := 'Error in procedure '||v_module_name||'. Error Details: '|| SUBSTR(SQLERRM, 1, 900);
      INSERT INTO SGA_W_LOG (  procedure_name,  data,  ts_last_modified)
      VALUES(v_module_name,v_msg_text, SYSDATE);
      COMMIT;
  END MULTI_DELETE;
/


Step 3.
post_run_steps.shsqlplus /nolog @post_run_steps.sql
post_run_steps.bat
sqlplus /nolog @post_run_steps.sql

post_run_steps.sql
@../set_vipuser.sqlSET SERVEROUT ON
SET HEADING OFF
SET LINESIZE 400
SET PAGESIZE 0
SET FEEDBACK OFF
PROMPT conn &&vipuser/&&vippass@&&connectStr
conn &&vipuser/&&vippass@&&connectStr

EXEC DBMS_OUTPUT.ENABLE(100000);
PROMPT DROP TABLE 
SOURCE_DATA_SUBSCRIBER_BAK
DROP TABLE 
SOURCE_DATA_SUBSCRIBER_BAK;
PROMPT DROP TABLE SGA_LOC_GRP_OUTBACK_NETWORKS
DROP TABLE SGA_LOC_GRP_OUTBACK_NETWORKS;
PROMPT DROP TABLE MSISDN_PROFILE_NOT_PRE
DROP TABLE MSISDN_PROFILE_NOT_PRE;
PROMPT Finished Post Run step
EXIT;

Sunday, April 22, 2018

Golden Gate Lag at Chkpt is high. What does it mean?

==========================
General
==========================
The issue: One of the Oracle GG (Golden Gate) EXTRACT  processes was in ABENDED status. 
After fixing the underlying problem , the value for Lag at Chkpt is high.
What does it mean?


>%cd /software/ogg/1212
/software/ogg/1212/>% ./ggsci
info all

GGSCI (esp-tel-1-dbu-2) 26> info all

Program     Status      Group       Lag at Chkpt  Time Since Chkpt

MANAGER     RUNNING  
EXTRACT     RUNNING     EXT_I_01    00:00:06      00:00:06    
EXTRACT     RUNNING     EXT_I_02    00:00:05      00:00:02    
EXTRACT     RUNNING     EXT_I_04    00:00:06      00:00:04    
EXTRACT     RUNNING     EXT_I_05    00:00:06      00:00:02    
EXTRACT     RUNNING     EXT_I_06    00:00:07      00:00:10
EXTRACT     RUNNING     EXT_I_07    83:06:52      00:00:09
EXTRACT     RUNNING     EXT_S_02    00:00:05      00:00:07    
EXTRACT     RUNNING     EXT_S_04    00:00:05      00:00:02    
EXTRACT     RUNNING     EXT_S_05    00:00:05      00:00:03    
EXTRACT     RUNNING     EXT_S_06    00:00:05      00:00:03    
EXTRACT     RUNNING     EXT_S_07    96:46:27      00:00:01    


==========================
Explanation
==========================
Time Since Checkpoint and Lag at Checkpoint

Time Since Checkpoint
Each process has it's own checkpoint file. 
Whenever a process see's a commit in the transaction, a checkpoint is made in the checkpoint file. 

You can see the increase in the Time Since Checkpoint, when extract was stopped or when extract or replicat is processing a long running transaction

If you stop a Extract process at 10:00AM and restart it at 10:30 AM, upon restarting, the Extract process reads it's checkpoint file to know the last successful processed transaction. And it starts processing all the transactions after that checkpoint.

You can see the increase in the Time Since Checkpoint, when extract or replicat is processing a long running transaction. 
By using the SEND EXTRACT STATUS or SEND REPLICAT STATUS command you can know the exact status of the processes. 
The INFO command always fetches the information from the checkpoint file.
The SEND command communicates directly with the process and gets the current/latest status of it.


Lag at Checkpoint
For Extract, lag is the difference, in seconds, between the time that a record was processed by Extract (based on the system clock) and the timestamp of that record in the data source.

For Replicat, lag is the difference, in seconds, between the time that the last record was processed by Replicat (based on the system clock) and the timestamp of the record in the trail.

 ==========================
Resolution
==========================
Nothing to do, just wait.
The Extract was in Abended state for several hours, and it got a backlog of transactions to reprocess.
After ~10 minutes, the Lag at Checkpoint was reduced from ~90 minutes to ~70 minutes


GGSCI (my_server) 757> SEND REPLICAT REP_I_01 STATUS

Sending STATUS request to REPLICAT REP_I_01 ...
  Current status: Processing data
  Sequence #: 4,614
  RBA: 428,201,835
  275,562 records in current transaction.


GGSCI (my_server) 758> SEND REPLICAT REP_I_01 STATUS

Sending STATUS request to REPLICAT REP_I_01 ...
  Current status: Processing data
  Sequence #: 4,614
  RBA: 429,066,155
  277,022 records in current transaction.


The Transaction is not yet completed.

GGSCI (esp-tel-1-dbu-2) 26> info all

Program     Status      Group       Lag at Chkpt  Time Since Chkpt

MANAGER     RUNNING                    
EXTRACT     RUNNING     EXT_I_01    00:00:06      00:00:08    
EXTRACT     RUNNING     EXT_I_02    00:00:05      00:00:03    
EXTRACT     RUNNING     EXT_I_04    00:00:06      00:00:08    
EXTRACT     RUNNING     EXT_I_05    00:00:06      00:00:08    
EXTRACT     RUNNING     EXT_I_06    00:00:07      00:00:07    

EXTRACT     RUNNING     EXT_I_07    64:58:26      00:00:01 
EXTRACT     RUNNING     EXT_S_01    00:00:05      00:00:03    
EXTRACT     RUNNING     EXT_S_02    00:00:05      00:00:03    
EXTRACT     RUNNING     EXT_S_04    00:00:06      00:00:08    
EXTRACT     RUNNING     EXT_S_05    00:00:05      00:00:02    
EXTRACT     RUNNING     EXT_S_06    00:00:06      00:00:08    
EXTRACT     RUNNING     EXT_S_07    78:51:46      00:00:01    


After additional ~10 minutes, the Lag at Checkpoint was reduced further.
EXTRACT     RUNNING     EXT_I_01    00:00:06      00:00:07    
EXTRACT     RUNNING     EXT_I_02    00:00:06      00:00:07    
EXTRACT     RUNNING     EXT_I_04    00:00:06      00:00:07    
EXTRACT     RUNNING     EXT_I_05    00:00:06      00:00:07    
EXTRACT     RUNNING     EXT_I_06    00:00:05      00:00:03    
EXTRACT     RUNNING     EXT_I_07    54:01:19      00:00:08   
EXTRACT     RUNNING     EXT_S_01    00:00:06      00:00:07    
EXTRACT     RUNNING     EXT_S_02    00:00:06      00:00:06    
EXTRACT     RUNNING     EXT_S_04    00:00:06      00:00:07    
EXTRACT     RUNNING     EXT_S_05    00:00:06      00:00:07    
EXTRACT     RUNNING     EXT_S_06    00:00:06      00:00:07    
EXTRACT     RUNNING     EXT_S_07    66:03:33      00:00:07  

Golden Gate Extract is in Abended state because of OGG-01496 Failed to open target trail file

==========================
General
==========================
The issue: One of the Oracle GG (Golden Gate) EXTRACT  processes is in ABENDED status

>%cd /software/ogg/1212
/software/ogg/1212/>% ./ggsci
info all

EXTRACT     RUNNING     EXT_S_04    00:00:06      00:00:06    
EXTRACT     RUNNING     EXT_S_05    00:00:05      00:00:01    
EXTRACT     RUNNING     EXT_S_06    00:00:06      00:00:06    
EXTRACT     ABENDED     EXT_S_07    00:00:06      144:13:03   
EXTRACT     RUNNING     EXT_S_09    00:00:05      00:00:01    
EXTRACT     RUNNING     EXT_S_10    00:00:06      00:00:06    
EXTRACT     RUNNING     EXT_S_11    00:00:05      00:00:01    
EXTRACT     RUNNING     EXT_S_12    00:00:05      00:00:01    
EXTRACT     RUNNING     EXT_S_13    00:00:06      00:00:06  

==========================
Investigation and resolution
==========================
/software/ogg/1212/>% ./ggsci
VIEW REPORT EXT_S_07
...
...
Database Version:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE    11.2.0.4.0      Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production

Database Language and Character Set:
NLS_LANGUAGE     = "AMERICAN" 
NLS_TERRITORY    = "AMERICA" 
NLS_CHARACTERSET = "AL32UTF8" 

2018-04-22 06:59:58  INFO    OGG-02089  Source redo compatibility version is: 11.2.0.4.

2018-04-22 06:59:59  WARNING OGG-02045  Database does not have streams_pool_size initialization parameter configured.

2018-04-22 07:00:00  INFO    OGG-02068  Integrated capture successfully attached to logmining server OGG$CAP_EXT_S_07 using OGGCapt
ure API.

2018-04-22 07:00:00  INFO    OGG-02086  Integrated Dictionary will be used.

Source Context :
  SourceModule            : [er.recovery]
  SourceID                : [/scratch/aime1/adestore/views/aime1_adc4150472/oggcore/OpenSys/src/app/er/recovery.c]
  SourceFunction          : [RECOVERY_initialize]
  SourceLine              : [1862]
  ThreadBacktrace         : [11] elements
                          : [/software/ogg/1212/libgglog.so(CMessageContext::AddThreadContext()+0x1e) [0x7f3ad7f15dee]]
                          : [/software/ogg/1212/libgglog.so(CMessageFactory::CreateMessage(CSourceContext*, unsigned int, ...)+0x31
c) [0x7f3ad7f12c2c]]
                          : [/software/ogg/1212/libgglog.so(_MSG_ERR_RECOVERY_OPEN_FAILED(CSourceContext*, char const*, int, CMessa
geFactory::MessageDisposition)+0x3c) [0x7f3ad7eef8fc]]
                          : [/software/ogg/1212/extract(RECOVERY_initialize()+0x3e6) [0x5623f6]]
                          : [/software/ogg/1212/extract(extract_main(int, char**)+0x34b) [0x5b0a1b]]
                          : [/software/ogg/1212/extract(ggs::gglib::MultiThreading::MainThread::ExecMain()+0x4f) [0x68743f]]
                          : [/software/ogg/1212/extract(ggs::gglib::MultiThreading::Thread::RunThread(ggs::gglib::MultiThreading::T
hread::ThreadArgs*)+0x104) [0x687694]]
                          : [/software/ogg/1212/extract(ggs::gglib::MultiThreading::MainThread::Run(int, char**)+0x8b) [0x68785b]]
                          : [/software/ogg/1212/extract(main+0x3f) [0x5b047f]]
                          : [/lib64/libc.so.6(__libc_start_main+0xfd) [0x3998c1ed1d]]
                          : [/software/ogg/1212/extract() [0x51dc59]]

2018-04-22 07:00:00  ERROR   OGG-01496  Failed to open target trail file /software/ogg/1212/dirdat/07/out/es000436, at RBA 35310590
.

2018-04-22 07:00:00  ERROR   OGG-01668  PROCESS ABENDING.

GGSCI (esp-tel-2-dbu-2) 1> ALTER EXT_I_07 ETROLLOVER

2018-04-22 08:00:46  INFO    OGG-01520  Rollover performed.  For each affected output trail of Version 10 or higher format, after starting the source extract, issue ALTER EXTSEQNO for that trail's reader (either pump EXTRACT or REPLICAT) to move the reader's scan to the new trail file;  it will not happen automatically.
EXTRACT altered.

GGSCI (esp-tel-2-dbu-2) 2> INFO EXT_I_07

EXTRACT    EXT_I_07  Initialized   2018-04-22 07:06   Status ABENDED
Checkpoint Lag       144:05:34 (updated 00:01:03 ago)
Log Read Checkpoint  Oracle Integrated Redo Logs
                     2018-04-16 07:55:12
                     SCN 3.2337132669 (15222034557)


GGSCI (esp-tel-2-dbu-2) 3> START EXTRACT EXT_I_07

Sending START request to MANAGER ...
EXTRACT EXT_I_07 starting


GGSCI (esp-tel-2-dbu-2) 4> INFO EXT_I_07

EXTRACT    EXT_I_07  Last Started 2018-04-22 08:02   Status RUNNING
Checkpoint Lag       144:06:58 (updated 00:00:06 ago)
Process ID           12870
Log Read Checkpoint  Oracle Integrated Redo Logs
                     2018-04-16 07:55:12
                     SCN 3.2337132669 (15222034557)



====================================================
What is the cause for "OGG-01496 Failed to open target trail file"?
====================================================
If existing extract output trail file was purged, it would cause the extract process to encounter this error.

By default, Extract Process writes EOF to trail file and the downstream Pump or Replicat process expect to see an EOF before switching to a next file.

The problem, is that Extract Process cannot write EOF to the current file because is was 
deleted or corrupted, and we need manually switch to next sequence file.

The solution is to use ETROLLOVER command and restart the EXTRACT.

====================================================
ETROLLOVER
====================================================
ETROLLOVER causes the extract to increment to the next trail file in the trail sequence when it restarts.


For example, if the current file is ET000002, the current file will be ET000003 when Extract restarts. 

A trail can be incremented from 000001 through 999999, and then the sequence numbering starts over at 000000.