Wednesday, August 29, 2012

12.1 Feature in Concurrent Processing

How concurrent program against a specific RAC instance with PCP/RAC setup?

You can specify 'Target Instance' . In 12.1.3, you can optionally specify a Real Application Cluster (RAC) instance on which the program will run. When requests for this program are submitted, they run on this instance if possible.

Navigation
System Administrator Responsibility > Concurrent > Program > Define > Click 'Session Control' 

Reference

Note 1129203.1 How to run a concurrent program against a specific RAC instance with PCP/RAC setup? 


Useful Queries related to Concurrent Requests

As part of day to day work, we need to use lot of queries to check the information about
concurrent requests. Here I am providing few queries which I frequently use for
day to day works and troubleshooting concurrent request / manager issues.


Note: The below queries needs to be run from APPS schema.

1. Scheduled concurrent requests:

Lot of times we need to find out the concurrent programs scheduled. USers can schedule
the concurrent requests in three ways (To run once at a specified time / To run periodically /
To run on specific days of the month or week).

The below query will return all the concurrent requests which are scheduled using
any of the above methods:

SELECT cr.request_id,
       DECODE (cp.user_concurrent_program_name,
               'Report Set', 'Report Set:' || cr.description,
               cp.user_concurrent_program_name
              ) NAME,
       argument_text, cr.resubmit_interval,
       NVL2 (cr.resubmit_interval,
             'PERIODICALLY',
             NVL2 (cr.release_class_id, 'ON SPECIFIC DAYS', 'ONCE')
            ) schedule_type,
       DECODE (NVL2 (cr.resubmit_interval,
                     'PERIODICALLY',
                     NVL2 (cr.release_class_id, 'ON SPECIFIC DAYS', 'ONCE')
                    ),
               'PERIODICALLY', 'EVERY '
                || cr.resubmit_interval
                || ' '
                || cr.resubmit_interval_unit_code
                || ' FROM '
                || cr.resubmit_interval_type_code
                || ' OF PREV RUN',
               'ONCE', 'AT :'
                || TO_CHAR (cr.requested_start_date, 'DD-MON-RR HH24:MI'),
               'EVERY: ' || fcr.class_info
              ) schedule,
       fu.user_name, requested_start_date
  FROM apps.fnd_concurrent_programs_tl cp,
       apps.fnd_concurrent_requests cr,
       apps.fnd_user fu,
       apps.fnd_conc_release_classes fcr
 WHERE cp.application_id = cr.program_application_id
   AND cp.concurrent_program_id = cr.concurrent_program_id
   AND cr.requested_by = fu.user_id
   AND cr.phase_code = 'P'
   AND cr.requested_start_date > SYSDATE
   AND cp.LANGUAGE = 'US'
   AND fcr.release_class_id(+) = cr.release_class_id
   AND fcr.application_id(+) = cr.release_class_app_id;
  

PS: The "SCHEDULE" column in the above query returns a string of zeros and ones for
the requests which are scheduled on specific days of the month or week.

Positions 1 through 31:  Specific day of the month.
Position  32:    Last day of the month
Positions 33 through 39:  Sunday through Saturday


2.  Checking the duplicated schedules of the same program with the same arguments:

The below query can be used to check the duplicated schedule of the same program
with the same arguments. This can be used to alert the users to cancel these duplicated
schedules.

PS: This query will return even though the request was submitted using a different responsibility.
SELECT   request_id, NAME, argument_text, user_name
    FROM (SELECT cr.request_id,
                 DECODE (cp.user_concurrent_program_name,
      ��                  'Report Set', 'Report Set:' || cr.description,
                         cp.user_concurrent_program_name
                        ) NAME,
                 argument_text, fu.user_name
            FROM apps.fnd_concurrent_programs_tl cp,
                 apps.fnd_concurrent_requests cr,
                 apps.fnd_user fu
           WHERE cp.application_id = cr.program_application_id
             AND cp.concurrent_program_id = cr.concurrent_program_id
             AND cr.requested_by = fu.user_id
             AND cr.phase_code = 'P'
             AND cr.requested_start_date > SYSDATE
             AND cp.LANGUAGE = 'US'
             AND fu.user_name NOT LIKE 'PPG%') t1
   WHERE EXISTS (
            SELECT   1
                FROM (SELECT cr.request_id,
                             DECODE (cp.user_concurrent_program_name,
                                     'Report Set', 'Report Set:'
                                      || cr.description,
                                     cp.user_concurrent_program_name
                                    ) NAME,
                             argument_text, fu.user_name
                        FROM apps.fnd_concurrent_programs_tl cp,
                             apps.fnd_concurrent_requests cr,
                             apps.fnd_user fu
                       WHERE cp.application_id = cr.program_application_id
                         AND cp.concurrent_program_id =
                                                      cr.concurrent_program_id
                         AND cr.requested_by = fu.user_id
                         AND cr.phase_code = 'P'
                         AND cr.requested_start_date > SYSDATE
                         AND cp.LANGUAGE = 'US'
                         AND fu.user_name NOT LIKE 'PPG%') t2
               WHERE t1.NAME = t2.NAME
                 AND t1.argument_text = t2.argument_text
                 AND t1.user_name = t2.user_name
            GROUP BY NAME, argument_text, user_name
              HAVING COUNT (*) > 1)
ORDER BY user_name, NAME


3. Average pending time per request:

This is a very useful query to check the performance of the concurrent managers.
Average pending time for a request is calculated like below:
("Highest of Requested_start_date or Date_submitted" - Actual_start_date ) / Total requests

A Request can be in Pending state for variety of reasons like conflict with other requests,
improperly tuned managers (sleep seconds / cache size / number of managers etc)

We can schedule this script to gather data regularly for historical analysis as we normally
purge the concurrent requests regularly.


SELECT   TO_CHAR (actual_start_date, 'DD-MON-YYYY') DAY,
         concurrent_queue_name,
           (SUM (  (  actual_start_date
                    - (CASE
                          WHEN requested_start_date > request_date
                             THEN requested_start_date
                          ELSE request_date
                       END
                      )
                   )
                 * 24
                 * 60
                 * 60
                )
           )
         / COUNT (*) "Wait_Time_per_Req_in_Secs"
    FROM apps.fnd_concurrent_requests cr,
         apps.fnd_concurrent_processes fcp,
         apps.fnd_concurrent_queues fcq
   WHERE cr.phase_code = 'C'
     AND cr.actual_start_date IS NOT NULL
     AND cr.requested_start_date IS NOT NULL
     AND cr.controlling_manager = fcp.concurrent_process_id
     AND fcp.queue_application_id = fcq.application_id
     AND fcp.concurrent_queue_id = fcq.concurrent_queue_id
GROUP BY TO_CHAR (actual_start_date, 'DD-MON-YYYY'), concurrent_queue_name
ORDER BY 2

PS: Depending on the purging schedules some requests might miss if the corresponding
data in fnd_concurrent_processes is purged.


4. Checking which manager is going to execute a program:

The below query identifies the manager which will be executing a given program.
This query is based on the specialization rules set for the managers.


SELECT user_concurrent_program_name, user_concurrent_queue_name
  FROM apps.fnd_concurrent_programs_tl cp,
       apps.fnd_concurrent_queue_content cqc,
       apps.fnd_concurrent_queues_tl cq
 WHERE cqc.type_application_id(+) = cp.application_id
   AND cqc.type_id(+) = cp.concurrent_program_id
   AND cqc.type_code(+) = 'P'
   AND cqc.include_flag(+) = 'I'
   AND cp.LANGUAGE = 'US'
   AND cp.user_concurrent_program_name = '&USER_CONCURRENT_PROGRAM_NAME'
   AND NVL (cqc.concurrent_queue_id, 0) = cq.concurrent_queue_id
   AND NVL (cqc.queue_application_id, 0) = cq.application_id
   AND cq.LANGUAGE = 'US'
  
5. To see all the pending / Running requests per each manager wise:


SELECT   request_id, phase_code, status_code, user_name,
         user_concurrent_queue_name
    FROM apps.fnd_concurrent_worker_requests cwr,
         apps.fnd_concurrent_queues_tl cq,
         apps.fnd_user fu
   WHERE (cwr.phase_code = 'P' OR cwr.phase_code = 'R')
     AND cwr.hold_flag != 'Y'
     AND cwr.requested_start_date <= SYSDATE
     AND cwr.concurrent_queue_id = cq.concurrent_queue_id
     AND cwr.queue_application_id = cq.application_id
     AND cq.LANGUAGE = 'US'
     AND cwr.requested_by = fu.user_id
ORDER BY 5

PS: The same information can be seen in Administer Concurrent Manager form for each manager.

6. Checking the incompatibilities between the programs:

The below query can be used to find all incompatibilities in an application instance.
SELECT a2.application_name, a1.user_concurrent_program_name,
                DECODE (running_type,
                        'P', 'Program',
                        'S', 'Request set',
                        'UNKNOWN'
                       ) "Type",
                b2.application_name "Incompatible App",
                b1.user_concurrent_program_name "Incompatible_Prog",
                DECODE (to_run_type,
                        'P', 'Program',
                        'S', 'Request set',
                        'UNKNOWN'
                       ) incompatible_type
           FROM apps.fnd_concurrent_program_serial cps,
                apps.fnd_concurrent_programs_tl a1,
                apps.fnd_concurrent_programs_tl b1,
                apps.fnd_application_tl a2,
                apps.fnd_application_tl b2
          WHERE a1.application_id = cps.running_application_id
            AND a1.concurrent_program_id = cps.running_concurrent_program_id
            AND a2.application_id = cps.running_application_id
            AND b1.application_id = cps.to_run_application_id
            AND b1.concurrent_program_id = cps.to_run_concurrent_program_id
            AND b2.application_id = cps.to_run_application_id
            AND a1.language = 'US'
            AND a2.language = 'US'
            AND b1.language = 'US'
            AND b2.language = 'US'


The table apps.fnd_concurrent_program_serial has the information about incompatibilities.

cmclean.sql internal job

Update process status codes to TERMINATED
Updating invalid process status codes in FND_CONCURRENT_PROCESSES
Set all managers to 0 processes
prompt -- Updating running processes in FND_CONCURRENT_QUEUES
prompt -- Setting running_processes = 0 and max_processes = 0 for all managers

Reset control codes
Updating invalid control_codes in FND_CONCURRENT_QUEUES
Also null out target_node for all managers
REM Set all 'Terminating' requests to Completed/Error
REM Also set Running requests to completed, since the managers are down

Updating any Running or Terminating requests to Completed/Error
Set all Runalone flags to 'N'

INDEX REBUILD

ORACLE
When should you rebuild index and how?
Oracle's index rebuilding guidelines appear in recommends that indexes be periodically examined to see if they are candidates for an index rebuild:
“When an index is skewed, parts of an index are accessed more frequently than others. As a result, disk contention may occur, creating a bottleneck in performance.  It is important to periodically examine your indexes to determine if they have become skewed and might need to be rebuilt.”
Oracle index nodes are not physically deleted when table rows are deleted, nor are the entries removed from the index. Rather, Oracle "logically" deletes the index entry and leaves "dead" nodes in the index tree where that may be re-used if another adjacent entry is required.  However, when large numbers of adjacent rows are deleted, it is highly unlikely that Oracle will have an opportunity to re-use the deleted leaf rows, and these represent wasted space in the index. In addition to wasting space, large volumes of deleted leaf nodes will make index fast-full scans run for longer periods.  These deleted leaf nodes can be easily identified by running the IDL.SQL script.

The number of deleted leaf rows

The term "deleted leaf node" refers to the number of index inodes that have been logically deleted as a result of row deletes. Remember that Oracle leaves "dead" index nodes in the index when rows are deleted. This is done to speed up SQL deletes, since Oracle does not have to allocate resources to rebalance the index tree when rows are deleted.

Index height

The height of the index refers to the number of levels that are spawned by the index as a result in row inserts. When a large amount of rows are added to a table, Oracle may spawn additional levels of an index to accommodate the new rows.

Oracle indexes can support many millions of entries in three levels.  Any Oracle index that has spawned to a 4th level followed by a large delete job might benefit from rebuilding to restore the index to its pristine state.

Gets per index access

The number of "gets" per access refers to the amount of logical I/O that is required to fetch a row with the index. As you may know, a logical "get" is not necessarily a physical I/O since much of the index may reside in the Oracle buffer cache.

Unfortunately, Oracle does not make it easy to capture this information. In Oracle we must issue these commands to populate the statistics in dba_indexes and related dictionary tables:

ANALYZE INDEX index_name COMPUTE STATISTICS
ANALYZE INDEX index_name VALIDATE STRUCTURE

We might want to rebuild an index if the “block gets” per access is excessive.  This happens when an index becomes "sparse" after high delete activity, making full-index scans requires unnecessary I/O. Another rebuild condition would be cases where deleted leaf nodes comprise more than 20% of the index nodes.

How to rebuild index?
As you may know, you can easily rebuild an Oracle index with the command:

ALTER INDEX index_name REBUILD tablespace FLOP;

Done properly during scheduled downtime, rebuilding an index is 100% safe.  Note the use of the tablespace option.  When rebuilding multi-gigabyte indexes, many DBA's will rebuild partitioned indexes into a fresh, empty tablespace for greater manageability.

The ALTER INDEX index_name REBUILD command is very safe way to rebuild indexes. Here is the syntax of the command:

alter index index_name
rebuild
tablespace tablespace_name
storage (initial new_initial next new_next freelists new_freelist_number )

Unlike the traditional method where we drop the index and recreate it, the REBUILD command does not require a full table scan of the table, and the subsequent sorting of the keys and rowids. Rather, the REBUILD command will perform the following steps:
1.         Walk the existing index to get the index keys.
2.         Populate temporary segments with the new tree structure.
3.         Once the operation has completed successfully, drop the old tree, and rename the temporary segments to the new index.
As you can see from the steps, you can rebuild indexes without worrying that you will accidentally lose the index. If the index cannot be rebuilt for any reason, Oracle will abort the operation and leave the existing index intact. Only after the entire index has been rebuilt does Oracle transfer the index to the new b-tree.

Note that the TABLESPACE clause should always be used with the ALTER INDEX REBUILD command to ensure that the index is not rebuilt within the default tablespace (usually SYS). It's always a good idea to move an index into another tablespace and you must have enough room in that tablespace to hold all of the temporary segments required for the index rebuild, so most Oracle administrators will double-size index tablespaces with enough space for two full index trees.


LOCAL LISENER vs REMOTE LISTENER

you're right, LOCAL_LISTENER on each node should point to the listener on that node.
REMOTE_LISTENER should point to all listeners on all nodes if you want server side load balancing,
otherwise don't set REMOTE_LISTENER.
Use listener_<instance_name> as the alias name for the local listener, and listeners_<servicename> for the remote listener alias.

     Quick explanation :
     The SERVICE_NAME=VIS is standing for the 4 RAC instances : VIS1, VIS2, VIS3 and VIS4.
     The Apps user will connect to the 11i/RAC via the SERVICE_NAME=VIS, and the Rac engine will
      randomly switch the users to "one of" the RAC instance (VIS1, VIS2,VIS3 or VIS4)  where has the
      lower load compare to the 3 other instances, this mechanism is calling the RAC Load balancing.

the remote_listener parameter points to your SCAN listener(s) which will do the load balancing, and local_listener points to the node listener which will do the spawn-and-bequeath.
When a SCAN Listener receives a connection request, the SCAN Listener will check for the least loaded instance
providing the requested service. It will then re-direct the connection request to the local listener on the node where the
least loaded instance is running. Subsequently, the client will be given the address of the local listener. The local listener
will finally create the connection to the database instance.
  
http://www.oracle.com/technetwork/database/clustering/overview/scan-129069.pdf
How To Find Out The Example of The LOCAL_LISTENER and REMOTE_LISTENER Defined In The init.ora When configuring the 11i or R12 on RAC ? [ID 744508.1]
http://www.comp.dit.ie/btierney/oracle11gdoc/install.111/b28264/undrstnd.htm

Solving Concurrent Program “Pending Standby” status

1. Concurrent request status is PENDING STANDBY status?
Pending Standby  - Phase Pending and Status Standby means Program to run request is incompatible with other program(s) currently running.
 I have submitted one concurrent request at 19:00 Hrs (Day1) and this request is to be run by a concurrent manager which has work shift of 00:00 Hrs to 08:00 Hrs (Day 2). The moment when I submit this concurrent request it’s status will be “Inactive No Manager” until this manager goes active. Suppose I have many requests pending with this concurrent and this request couldn’t start.
Now what will be status of this request after 08:00 Hrs (Day 2) when it’s manager goes down? Here in my case it is still “Inactive No Manager” though I think it should be “Pending Standby”
This could be for different reasons (other pending requests, no place for new requests, ...etc).
Solving Concurrent Program “Pending Standby” status (Oracle EBS 11i)
There are instances when we run the Concurrent Program, it goes to “Pending Standby” status. Sometimes we can see this status get changed after few minutes but,
there are instances it will be in the same status forever. This means the request is not progressing and will not be completed ever.
To make that request to progress again, the following steps need to be carried out; Go to System Administrator Responsibility;
——>>System Administrator
————>Concurrent manager
——————–>Conflict Resolution Manager
See whether the Conflict Resolution manager is running, if is it not, activate it and it will solve the standby status issue.
If the Conflict Resolution manager is running
——->Click “Verify” button
Once completed with the verification, resubmit the previous hanging request, and it should run without any problem.

DR REBUILD procedure

dr REBUILD PROCEDURE:
====================
1. Shutdown the standby database if it is running.
a) First cancel the recovery
sqlplus / as sysdba
sql> recover managed standby database cancel;
sql>shutdown immediate
b) stop the listener.
2. Put the all tablespaces in hot backup mode in prod.
3. Have SAN Administrator to Split the Disks and mount the disks on the standby server.
4. Put end hot backup on all tablespaces
5. create the standby control file
ALTER DATABASE CREATE STANDBY CONTROLFILE AS '/tmp/boston.ctl';
6. rsync the standby controlfile to the standby server
7. Bringup the standby db
a) copy the control file to normal control files loc.
b)create standby spfile from pfile
c)start standby listener
d)mount standby db and
start recovery =  alter database recover managed standby database disconnect from session;

8. Verify the standby recovery progress
a) Start remote archiving by forcing a log switch on the primary database node
$ sqlplus <user>/<pass>
SQL> alter system archive log current;
b) Tail the Standby Database alert log to verify there are no errors and make sure archive log switched
in previous step received by standby and Media Recovery delayed by 60 minutes for the log
9. Schedule archive job for standby db.