Pages

Monday, December 18, 2023

Change resource of a profile

Change resource of a profile by Example.

Example: Change IDLE_TIME from 480 minutes to UNLIMITED

SELECT profile, resource_name, limit 
  FROM DBA_PROFILES 
 WHERE limit NOT IN ('UNLIMITED','DEFAULT');

PROFILE              RESOURCE_NAME                    LIMIT
-------------------- -------------------------------- ---------------
APP_PROF             IDLE_TIME                        480
APP_PROF             PASSWORD_VERIFY_FUNCTION        
 ORA12C_STIG_VERIFY_FUNCTION
GSM_PROF             FAILED_LOGIN_ATTEMPTS            10000000
DEFAULT              PASSWORD_VERIFY_FUNCTION         NULL
DEFAULT              PASSWORD_LOCK_TIME               1
ORA_STIG_PROFILE     IDLE_TIME                        15
ORA_STIG_PROFILE     FAILED_LOGIN_ATTEMPTS            3
ORA_STIG_PROFILE     PASSWORD_LIFE_TIME               60
ORA_STIG_PROFILE     PASSWORD_REUSE_TIME              365
ORA_STIG_PROFILE     PASSWORD_REUSE_MAX               10
ORA_STIG_PROFILE     PASSWORD_VERIFY_FUNCTION         ORA12C_STIG_VERIFY_FUNCTION
ORA_STIG_PROFILE     PASSWORD_GRACE_TIME              5
ORA_STIG_PROFILE     INACTIVE_ACCOUNT_TIME            35


ALTER PROFILE APP_PROF LIMIT IDLE_TIME UNLIMITED;

SELECT profile, resource_name, limit 
  FROM DBA_PROFILES 
 WHERE resource_name ='IDLE_TIME';


PROFILE              RESOURCE_NAME                    LIMIT
-------------------- -------------------------------- ---------------
DEFAULT              IDLE_TIME                        UNLIMITED
GSM_PROF             IDLE_TIME                        DEFAULT
ORA_STIG_PROFILE     IDLE_TIME                        15
APP_PROF             IDLE_TIME                        UNLIMITED
 
Note: This will effect only new sessions. 

Thursday, December 14, 2023

AWR "enq: TX - row lock contention" Wait Event

=============================
General
=============================
Checking AWR, Oracle is spending a lot of time in "enq: TX - row lock contention" waits.
How to troubleshoot?

                                                   Avg        %Total
                                   %Tim Total Wait wait Waits Call
Event                        Waits  out   Time (s) (ms) /txn  Time
---------------------------- ----- ---- ---------- ---- ----- ------
enq: TX - row lock contentio    21    0         85 4049   0.0     .2
1. Get the sessions that are in waiting state.
2. Get the blocking session of these sessions.
3. See what the blocking session is running

=============================
To get the history SQLs in waiting state:
=============================
Get summary for last intervals
SELECT LOCKS_SUMMARY.locks, 
       LOCKS_SUMMARY.snap_id, 
       LOCKS_SUMMARY.sample_time, 
       LOCKS_SUMMARY.sql_id, 
       SQLAREA.sql_fulltext
  FROM V$SQLAREA SQLAREA, 
(SELECT COUNT(*) as locks, 
       snap_id, TO_CHAR(sample_time,'YYYYMMDD hh24') sample_time, 
       sql_id
  FROM dba_hist_active_sess_history hist
 WHERE wait_class != 'Idle' 
   AND event = 'enq: TX - row lock contention'
GROUP BY snap_id, TO_CHAR(sample_time,'YYYYMMDD hh24'),sql_id
 ORDER BY snap_id DESC,  COUNT(*) DESC
  ) LOCKS_SUMMARY
WHERE SQLAREA.sql_id = LOCKS_SUMMARY.sql_id
ORDER BY 2 desc, 1 desc, 3;


Get details for last intervals
SELECT snap_id, sample_time, session_id,  
       SQLAREA.sql_id, 
       SQLAREA.sql_text
  FROM dba_hist_active_sess_history hist, 
       v$sqlarea SQLAREA
 WHERE wait_class != 'Idle' 
   AND event = 'enq: TX - row lock contention'
   AND SQLAREA.sql_id = hist.sql_id
 ORDER BY snap_id DESC, sample_time DESC;
 
Get details for last interval
SELECT snap_id, session_type, sql_id, event, program , machine, port
  FROM dba_hist_active_sess_history
 WHERE snap_id = (SELECT MAX(snap_id) FROM DBA_HIST_SNAPSHOT)
   AND event = 'enq: TX - row lock contention';

=============================
To get the current SQLs in waiting state:
============================= 
set linesize 140
set pagesize 1000

SELECT SESSIONS.sid, 
       SESSIONS.sql_id, 
       SUBSTR(SQLS.sql_text ,1,30) as sql_text,
       SESSIONS.program, 
       SESSIONS.schemaname, 
       SESSIONS.machine, 
       SESSIONS.port
  FROM V$SESSION SESSIONS,
       V$SQL SQLS 
 WHERE SESSIONS.sid IN 
       (SELECT sid  
          FROM V$SESSION 
         WHERE state in ('WAITING') 
           AND wait_class != 'Idle' 
           AND event='enq: TX - row lock contention'
   AND schemaname IS NOT NULL
        )
   AND  SQLS.sql_id = SESSIONS.sql_id;

============================= 
To get the Blocking session:
============================= 

SELECT blocking_session, 
       sid, 
       serial#, 
       wait_class, 
       seconds_in_wait 
  FROM V$SESSION 
 WHERE blocking_session is not NULL 
ORDER BY blocking_session;

Output is missing, but blocking session was 401.

============================= 
See what blocking session is running:
============================= 
SELECT USERNAME, SQL_ID FROM V$SESSION WHERE blocking_session=401;

USERNAME                       SQL_ID
------------------------------ -------------
MY_USER                        d94vtj1qqdvct


SELECT SQL_TEXT FROM V$SQLAREA
 WHERE sql_id = 'd94vtj1qqdvct';

SQL_TEXT
-------------------------------------------------------------------------------------
MERGE into SGA_W_SUBSCRIBER o using (select :1  MSISDN from dual) o1 on (o.MSISDN = o1.MSISDN) when matched then updateset o.IMSI= :2 ,o.DYNAMIC_COMMUNITIES =:3 ,o.CURRENT_COUNTRY= :4 ,o.CURRENT_NETWORK_ID = :5  , o.CURRENT_VLR = :6  ,o.CURRENT_MSC = :7  , o.TS_FIRST_REGISTRATION = :8  ,o.TS_E_LAST_LU = :9  , o.IS_ROAMING = :10 , o.TS_LAST_ROAMER_EVENT = :11 , o.CURRENT_SGSN = :12   ,o.NON_PURGEABLE_COUNT = :13 , o.PREVIOUS_VLR=:14 ,o.PREVIOUS_SGSN=:15 , o.TS_E_LAST_CANCEL=:16 , o.TS_E_LAST_PURGE=:17 , o.TS_E_LAST_SRI4SM_REQ=:18 , o.TS_VISIT_START=:19 , o.TS_VISIT_END=:20 , o.TS_LAST_MODIFIED=:21 , o.MAP_CATEGORY=:22 , o.MAP_CAMEL_PHASE=:23 , o.MAP_CAMEL_SERVICE_KEY=:24 , o.MAP_BARRING_INDICATION=:25 , o.MAP_BARRING_INDICATION_TS=:26 , o.MAP_FTN_BUSY=:27 , o.MAP_FTN_BUSY_TS=:28 , o.MAP_FTN_BUSY_TEL_SERVICE=:29 , o.MAP_FTN_BUSY_STATUS=:30 , o.MAP_FTN_NOREPLY=:31 , o.MAP_FTN_NOREPLY_TS=:32 , o.MAP_FTN_NOREPLY_TEL_SERVICE=:33 , o.MAP_FTN_NOREPLY_STATUS=:34 , o.MAP_FTN_NOREPLY_TIMEOUT=:






============================= 
See locks by sql_id:
============================= 
1st
SELECT sample_id,
       TO_CHAR(sample_time,'YYYYMMDD hh24:mi') as sample_min,
       LOCKS_HIST.session_id as locked_sid,
       LOCKS_HIST.session_serial# as locked_serial,
       LOCKS_HIST.sql_id,
       LOCKS_HIST.sql_exec_start,
       LOCKS_HIST.event,
       LOCKS_HIST.session_state,
       LOCKS_HIST.blocking_session,
       LOCKS_HIST.program,
       LOCKS_HIST.module, 
       LOCKS_HIST.machine,
       LOCKS_HIST.port,
       LOCKS_HIST.session_state,
       LOCKS_HIST.blocking_session,
       LOCKS_HIST.blocking_session_serial#
  FROM DBA_HIST_ACTIVE_SESS_HISTORY LOCKS_HIST
 WHERE sql_id = '2xkrv2tcm98sn'
   AND sample_time > TRUNC(SYSDATE);

2nd.
Take blocking_sessions from 1st SQL

SELECT LOCKS_HIST.program,
       LOCKS_HIST.module, 
       LOCKS_HIST.machine,
       LOCKS_HIST.port
  FROM DBA_HIST_ACTIVE_SESS_HISTORY LOCKS_HIST 
 WHERE session_id IN (2331, 1152, 969, 2331);

3rd
SELECT CURRENT_SESSIONS.program,
       CURRENT_SESSIONS.module, 
       CURRENT_SESSIONS.machine,
       CURRENT_SESSIONS.port
  FROM V$SESSION CURRENT_SESSIONS 
WHERE sid IN (2331, 1152, 969, 2331);

Golden gate - crontab to log golden gate processes stats

 59 * * * * /software/oracle/oracle/scripts/gg_stats_monitor/get_gg_stats.sh

get_gg_stats.sh
#!/bin/bash
. /etc/sh/orash/oracle_login.sh igt
GG_HOME=/software/ogg/191
ORACLE_SID=igt
ORACLE_HOME=/software/oracle/122

HOME_DIR=/software/oracle/oracle/scripts/gg_stats_monitor
DAY_LOG_FILE="${HOME_DIR}/logs/gg_stats_daily.log"
HOUR_LOG_FILE="${HOME_DIR}/logs/gg_stats_hourly.log"
TEMP_HR_LOG=/tmp/gg_stats_hr.log
TEMP_DAY_LOG=/tmp/gg_stats_day.log

SCHEMA_NAME=XXX_YYYYY_ZZZZZ

RUN_HOUR=$(date +"%H")
RUN_DATE=`date +"%Y%m%d"_"%H%M%S"`

rm -f $TEMP_HR_LOG 2>/dev/null
rm -f $TEMP_DAY_LOG 2>/dev/null

$GG_HOME/ggsci > $TEMP_HR_LOG << EOD
STATS EXTRACT EXT_I_01, HOURLY
STATS EXTRACT EXT_P_01, HOURLY
STATS EXTRACT EXT_S_01, HOURLY
STATS REPLICAT REP_I_01, HOURLY
STATS REPLICAT REP_P_01, HOURLY
STATS REPLICAT REP_S_01, HOURLY
exit
EOD

if [[ $RUN_HOUR == "09" ]]; then
 $GG_HOME/ggsci > $TEMP_DAY_LOG << EOD
STATS EXTRACT EXT_I_01, DAILY
STATS EXTRACT EXT_P_01, DAILY
STATS EXTRACT EXT_S_01, DAILY
STATS REPLICAT REP_I_01, DAILY
STATS REPLICAT REP_P_01, DAILY
STATS REPLICAT REP_S_01, DAILY
exit
EOD
fi

echo "=======================" >> $HOUR_LOG_FILE
echo $RUN_DATE >> $HOUR_LOG_FILE
echo "=======================" >> $HOUR_LOG_FILE
less ${TEMP_HR_LOG} | grep -v "Command Interpreter for Oracle" | grep -v OGGCORE | grep -v "Operating system" | grep -v Copyright | grep -v "character set" | grep -v "Linux, x64" | grep -v GGSCI >> $HOUR_LOG_FILE

if [[ -f $TEMP_DAY_LOG ]]; then
 echo "=======================" >> $DAY_LOG_FILE
 echo $RUN_DATE >> $DAY_LOG_FILE
 echo "=======================" >> $DAY_LOG_FILE
 less ${TEMP_DAY_LOG} | grep -v "Command Interpreter for Oracle" | grep -v OGGCORE | grep -v "Operating system" | grep -v Copyright | grep -v "character set" | grep -v "Linux, x64" | grep -v GGSCI >> $DAY_LOG_FILE
fi

#=======================
# Keeps Logs for 1 Week
#=======================
if [[ $RUN_HOUR == "01" ]]; then
 mv ${HOUR_LOG_FILE}_06 ${HOUR_LOG_FILE}_07 2>/dev/null
 mv ${HOUR_LOG_FILE}_05 ${HOUR_LOG_FILE}_06 2>/dev/null
 mv ${HOUR_LOG_FILE}_04 ${HOUR_LOG_FILE}_05 2>/dev/null
 mv ${HOUR_LOG_FILE}_03 ${HOUR_LOG_FILE}_04 2>/dev/null
 mv ${HOUR_LOG_FILE}_02 ${HOUR_LOG_FILE}_03 2>/dev/null
 mv ${HOUR_LOG_FILE}_01 ${HOUR_LOG_FILE}_02 2>/dev/null
 mv ${HOUR_LOG_FILE} ${HOUR_LOG_FILE}_01 2>/dev/null

 mv ${DAY_LOG_FILE}_06 ${DAY_LOG_FILE}_07 2>/dev/null
 mv ${DAY_LOG_FILE}_05 ${DAY_LOG_FILE}_06 2>/dev/null
 mv ${DAY_LOG_FILE}_04 ${DAY_LOG_FILE}_05 2>/dev/null
 mv ${DAY_LOG_FILE}_03 ${DAY_LOG_FILE}_04 2>/dev/null
 mv ${DAY_LOG_FILE}_02 ${DAY_LOG_FILE}_03 2>/dev/null
 mv ${DAY_LOG_FILE}_01 ${DAY_LOG_FILE}_02 2>/dev/null
 mv ${DAY_LOG_FILE} ${DAY_LOG_FILE}_01 2>/dev/null
fi

Golden Gate - Crontab to log INFO ALL

crontab
*/10 * * * * /software/oracle/oracle/scripts/gg_stats_monitor/get_gg_info.sh

get_gg_info.sh
#!/bin/bash
. /etc/sh/orash/oracle_login.sh igt
GG_HOME=/software/ogg/191
ORACLE_SID=igt
ORACLE_HOME=/software/oracle/122

SCHEMA_NAME=XXX_YYYYY_ZZZZZ

HOME_DIR=/software/oracle/oracle/scripts/gg_stats_monitor
INFO_LOG_FILE="${HOME_DIR}/logs/gg_info.log"
TEMP_INFO_LOG=/tmp/gg_info_all.log

RUN_HOUR=$(date +"%H")
RUN_MIN=$(date +"%M")
RUN_DATE=`date +"%Y%m%d"_"%H%M%S"`

#main()
rm -f $TEMP_INFO_LOG 2>/dev/null

$GG_HOME/ggsci > $TEMP_INFO_LOG << EOD
INFO ALL
exit
EOD

echo "=======================" >> $INFO_LOG_FILE
echo $RUN_DATE >> $INFO_LOG_FILE
echo "=======================" >> $INFO_LOG_FILE
less ${TEMP_INFO_LOG} | grep -v "Command Interpreter for Oracle" | grep -v OGGCORE | grep -v "Operating system" | grep -v Copyright | grep -v "character set" | grep -v "Linux, x64" | grep -v GGSCI | grep -v "SYSLOG"  | grep -v ^$ >> $INFO_LOG_FILE


#=======================
# Keeps Logs for 1 Week
#=======================
if [[ $RUN_HOUR == "01" && $RUN_MIN == "00" ]]; then
 mv ${TEMP_INFO_LOG}_06 ${TEMP_INFO_LOG}_07 2>/dev/null
 mv ${TEMP_INFO_LOG}_05 ${TEMP_INFO_LOG}_06 2>/dev/null
 mv ${TEMP_INFO_LOG}_04 ${TEMP_INFO_LOG}_05 2>/dev/null
 mv ${TEMP_INFO_LOG}_03 ${TEMP_INFO_LOG}_04 2>/dev/null
 mv ${TEMP_INFO_LOG}_02 ${TEMP_INFO_LOG}_03 2>/dev/null
 mv ${TEMP_INFO_LOG}_01 ${TEMP_INFO_LOG}_02 2>/dev/null
 mv ${TEMP_INFO_LOG} ${TEMP_INFO_LOG}_01 2>/dev/null
fi

Generated File
=======================
20231214_082001
=======================
Program     Status      Group       Lag at Chkpt  Time Since Chkpt
MANAGER     RUNNING
EXTRACT     RUNNING     DPM_I_01    00:00:00      00:00:01
EXTRACT     RUNNING     DPM_P_01    00:00:00      00:00:08
EXTRACT     RUNNING     DPM_S_01    00:00:03      00:00:05
EXTRACT     RUNNING     EXT_I_01    00:00:02      00:00:05
EXTRACT     RUNNING     EXT_P_01    00:00:02      00:00:02
EXTRACT     RUNNING     EXT_S_01    00:00:02      00:00:02
REPLICAT    RUNNING     REP_I_01    00:00:00      00:00:04
REPLICAT    RUNNING     REP_P_01    00:00:00      00:00:08
REPLICAT    RUNNING     REP_S_01    00:00:03      00:00:00

Wednesday, December 6, 2023

ORA-32001: write to SPFILE requested but no SPFILE is in use

==========================
Error Details
==========================
ALTER SYSTEM SET MEMORY_MAX_TARGET=24576M scope=spfile;

ERROR at line 1:
ORA-32001: write to SPFILE requested but no SPFILE is in use


==========================
Solution
==========================

SQL> show parameter pfile

NAME            VALUE
--------------- --------------------
spfile          


Notice! - the value for spfile is not defined.

SQL> CREATE SPFILE FROM MEMORY;

spfile<inst>.ora is created under default location:
${ORACLE_HOME}/dbs/

/software/oracle/1910/dbs/spfileigt.ora

SQL> CREATE PFILE='/software/oracle/1910/dbs/pfileigt.ora' FROM SPFILE='/software/oracle/1910/dbs/spfileigt.ora'
PFILE is created:
/software/oracle/1910/dbs/pfileigt.ora


SQL> ALTER SYSTEM SET MEMORY_MAX_TARGET=24576M scope=spfile;
ALTER SYSTEM SET MEMORY_MAX_TARGET=24576M scope=spfile
*
ERROR at line 1:
ORA-32001: write to SPFILE requested but no SPFILE is in use

SQL> show parameter spfile

NAME              VALUE
----------------- ---------------------------------------
spfile

spfile is still not defined.
Need to restart oracle.


SQL> SHUTDOWN IMMEDIATE;
SQL> STARTUP;

SQL> show parameter spfile

NAME              VALUE
----------------- ---------------------------------------
spfile            /software/oracle/1910/dbs/spfileigt.ora


SQL> ALTER SYSTEM SET MEMORY_MAX_TARGET=24576M scope=spfile;

System altered.

SQL> ALTER SYSTEM SET MEMORY_TARGET=24576M scope=spfile;

System altered.

NAME                  VALUE
--------------------- -----------
memory_max_target     24G
memory_target         24G




Tuesday, December 5, 2023

Archive logs is pointing to non exiting location

===============================
The Problem:
===============================
Archive destination is not available.
Oracle is running in ARCHIVE mode.
This is giving errors during startup

SQL> shutdown immediate
ORA-01034: ORACLE not available
ORA-27101: shared memory realm does not exist
Linux-x86_64 Error: 2: No such file or directory
Or
SQL> shutdown immediate;
ORA-24324: service handle not initialized
ORA-01041: internal error. hostdef extension doesn't exist

SQL> startup mount;
ORA-16032: parameter LOG_ARCHIVE_DEST_1 destination string cannot be translated
ORA-07286: sksagdi: cannot obtain device information.
Linux-x86_64 Error: 2: No such file or directory


The problem is this parameter (LOG_ARCHIVE_DEST_1) is pointing to non existent locatoin.
To change the value of LOG_ARCHIVE_DEST_1:


===============================
Steps to resolve Problem:
===============================

A. locate spfileigt.ora
/software/oracle/admin/igt/pfile/spfileigt.ora


STARTUP NOMOUNT;

B. Create a pfileigt.ora

SQL> create pfile='/software/oracle/admin/igt/pfile/orig_pfile.ora' 

from spfile='/software/oracle/admin/igt/pfile/spfileigt.ora';


File created.


C. Edit the new pfile.ora. change location for log_archive_dest_1

cp orig_pfile.ora pfile.ora

vi pfile.ora

Change from:*.log_archive_dest_1='location=/path/does/not/exist'
To:log_archive_dest_1='location=/path/does/exist'

For example:
diff orig_pfile.ora pfile.ora 
27c27
< *.log_archive_dest_1='location=/oracle_db/db2/db_igt/arch'
---
> *.log_archive_dest_1='location=/oracle_db/db1/db_igt/arch'

D. Replace between files and start instance from new spfile

cp spfileigt.ora orig_spfileigt.ora

CREATE SPFILE='/software/oracle/admin/igt/pfile/spfileigt.ora' 
FROM PFILE='/software/oracle/admin/igt/pfile/pfile.ora';
ERROR at line 1:
ORA-32002: cannot create SPFILE already being used by the instance

CREATE SPFILE='/software/oracle/admin/igt/pfile/spfileigt.ora_new' 
FROM PFILE='/software/oracle/admin/igt/pfile/pfile.ora';

SHUTDOWN IMMEDIATE;
ORA-01507: database not mounted
ORACLE instance shut down.

mv spfileigt.ora_new spfileigt.ora

cd /software/oracle/admin/igt/pfile
/software/oracle/admin/igt/pfile>% ls -l
-rw-r--r-- 1 oracle dba 1296 Dec  5 07:52 orig_pfile.ora
-rw-r----- 1 oracle dba 3584 Dec  5 07:52 orig_spfileigt.ora
-rw-r--r-- 1 oracle dba 1296 Dec  5 07:54 pfile.ora
-rw-r----- 1 oracle dba 3584 Dec  5 08:08 spfileigt.ora


E. Restart the database
SQL> STARTUP NOMOUNT;
ORACLE instance started.

Total System Global Area 8589930592 bytes
Fixed Size                 12456032 bytes
Variable Size            4328521728 bytes
Database Buffers         4227858432 bytes
Redo Buffers               21094400 bytes
SQL> ALTER DATABASE MOUNT;

Database altered.

F. Optionally - change database to be in NOARCHIVELOG mode
SQL> ALTER DATABASE NOARCHIVELOG;

Database altered.

SQL> ALTER DATABASE OPEN;

Database altered.

SQL> SHUTDOWN IMMEDIATE;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> STARTUP;
ORACLE instance started.

Total System Global Area 8589930592 bytes
Fixed Size                 12456032 bytes
Variable Size            4328521728 bytes
Database Buffers         4227858432 bytes
Redo Buffers               21094400 bytes
Database mounted.
Database opened.
SQL> exit

G. Take backup with expdp

===================
In Short:
===================
Open two sessions
sqlplus 
STARTUP NOMOUNT;
CREATE PFILE='/software/oracle/admin/igt/pfile/orig_pfile.ora' 
FROM SPFILE='/software/oracle/admin/igt/pfile/spfileigt.ora';

Linux
cp orig_pfile.ora pfile.ora
vi pfile.ora
log_archive_dest_1='location=/oracle_db/db1/db_igt/arch

sqlplus 
CREATE SPFILE='/software/oracle/admin/igt/pfile/noarch_spfile.ora' 
FROM PFILE='/software/oracle/admin/igt/pfile/pfile.ora';

SHUTDOWN IMMEDIATE;

Linux 
cd /software/oracle/admin/igt/pfile
cp spfileigt.ora orig_spfileigt.ora
cp noarch_spfile.ora spfileigt.ora

sqlplus 
STARTUP NOMOUNT;
ALTER DATABASE MOUNT;
ALTER DATABASE NOARCHIVELOG;
ALTER DATABASE OPEN;
SHUTDOWN IMMEDIATE;
STARTUP;

Sunday, November 26, 2023

crontab to delete old dmp files

crontab
11 11 * * * /software/oracle/oracle/scripts/del_old_dmp_files/del_old_dmp.sh

del_old_dmp.sh
#!/bin/bash

WORK_DIR=/software/oracle/oracle/scripts/del_old_dmp_files
EXP_DIR=/backup/ora_exp
LOG_FILE=${WORK_DIR}/del_old_dmp.log
RUN_DATE=`date +"%Y%m%d"_"%H%M%S"`

cd ${WORK_DIR}
echo "=========================" >> ${LOG_FILE}
echo "Start Delete old dmp files at ${RUN_DATE}" >> ${LOG_FILE}

for f in `ls -1 ${EXP_DIR}  | grep export | grep dmp | grep igt`
do
 echo "Deleting File $f" >> ${LOG_FILE}
 echo "rm -f ${EXP_DIR}/$f" >> ${LOG_FILE}
 rm -f ${EXP_DIR}/$f
done
echo "=========================" >> ${LOG_FILE}

Wednesday, November 22, 2023

ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT

=====================
Error in oracle startup
=====================
SQL> Connected to an idle instance.
SQL> ORA-01078: failure in processing system parameters
ORA-00093: pga_aggregate_limit must be between 16384M and 100000G
SQL> Disconnected

=====================
What to check
=====================
COL name for A30
COL VALUE for A30
SELECT name, value 
  FROM V$PARAMETER 
 WHERE name = 'pga_aggregate_limit';

NAME                           VALUE
------------------------------ ------------------------------
pga_aggregate_limit            3145728000

3145728000=3000M


=====================
Solution
=====================
SQL> ALTER SYSTEM SET pga_aggregate_limit=0 SCOPE=BOTH;
System altered.

Issue resolved

=====================
Theory
=====================
As per Oracle documentation
In Oracle Database 12c, a new parameter called PGA_AGGREGATE_LIMIT sets a hard limit on the amount of PGA taken up by an instance. 
When the overall PGA occupied by all the sessions in that instance exceed the limit, Oracle kills the session holding the most untunable PGA memory, releasing all PGA memory held by that session.

Oracle PGA Memory Management
Theory
By default, Oracle Database automatically manages the total amount of memory dedicated to the instance PGA. 
You can control this amount by setting the initialization parameter PGA_AGGREGATE_TARGET.
This sets a logical ceiling to Oracle for all database server processes and background processes , but this ceiling can be exceeded.

What if the value is not set
If PGA_AGGREGATE_LIMIT is not set, then Oracle Database determines an appropriate default limit.
If PGA_AGGREGATE_TARGET is not set, the database chooses a default value for it.

Type of Control:
PGA_AGGREGATE_TARGET (Target): Acts as a target, not a strict limit. Oracle uses this to estimate the ideal memory for SQL operations.

PGA_AGGREGATE_LIMIT
 (Limit): Sets an absolute, hard maximum on the aggregate PGA memory that can be allocated.

Behavior When Exceeded:
Target: PGA can exceed the target, potentially causing swapping if it grows too high.
Limit: If this limit is hit, Oracle immediately terminates sessions consuming the most "untunable" PGA memory.

Calculate Values:
Target: Usually set manually by the DBA based on system memory.
Limit: Defaults to the greater of either 2GB, 200% of PGA_AGGREGATE_TARGET, or 3MB per process (up to 120% of physical memory minus SGA).

How to Calculate PGA_AGGREGATE_TARGET:
PGA_AGGREGATE_TARGET
is calculated based on available physical memory.
Take 80% of total OS memory(reserving 20% for the OS)
For OLTP systems it is typically set to 20% of the taken memory.      (Total Physical Memory * 0.8) * 0.2
For DSS/Data Warehouse systems it is set to 50% of the taken memory.  (Total Physical Memory * 0.8) * 0.5

PGA_AGGREGATE_LIMIT
SELECT limit_value*3 as 3x_proc_limit_mb 
  FROM V$RESOURCE_LIMIT 
 WHERE resource_name = 'processes';

Take the higher of these 3 values:
A. 2*PGA_AGGREGATE_TARGET,
B. 
3x_proc_limit_mb (above)
C. 2Gb
But... do not exceed 90% of physical memory minus total SGA.

To see the total SGA:
SELECT ROUND(SUM(value)/1024/1024) "TOTAL SGA (MB)" FROM V$SGA;

Purpose:
Target: Used for managing performance and tuning automatic memory usage in work areas (sorts, hashes).
Limit: Used to prevent overall PGA consumption from taking down the server by exhausting physical memory.



Monitor:
See Sizing estimated performance:
SELECT * FROM V$PGA_TARGET_ADVICE 
 ORDER BY pga_target_for_estimate;
 
See Current Usage:
SELECT ROUND(value/1024/1024) AS curr_pga_target_mb 
  FROM V$PGASTAT 
 WHERE name = 'aggregate PGA target parameter';

Maximum instance PGA allocated in megabytes since the database was started:
SELECT ROUND(value/1048576) as value_mb 
  FROM V$PGASTAT 
 WHERE name='maximum PGA allocated';


If AMM is used
If AMM (Automatic Memory Management) is used ( == MEMORY_TARGET set),  only the memory_target is set, and Oracle manages the PGA, and this parameter acts as a minimum.

With MEMORY_TARGET set, the SGA_TARGET setting becomes the minimum size of the SGA and the PGA_AGGREGATE_TARGET setting becomes the minimum size of the instance PGA.

By setting both of these to zero, there are no minimums, and the SGA and instance PGA can grow as needed.
The sizing of SQL work areas remains automatic.

In addition, you can use the PGA_AGGREGATE_LIMIT initialization parameter to set an instance-wide hard limit for PGA memory. You can set PGA_AGGREGATE_LIMIT whether or not you use automatic memory management. 

For AMM use:
SELECT * FROM V$MEMORY_TARGET_ADVICE ORDER BY memory_size;





If you are hitting ORA-04036: PGA memory used by the instance exceeds PGA_AGGREGATE_LIMIT error message you have 2 options
Option 1:
Set the value of pga_aggregate_limit to 0 and the parameter will not have any impact.
It behave like pre12c database.
ALTER SYSTEM SET PGA_AGGREGATE_LIMIT=0 SCOPE=BOTH;

Option 2:
Set this value to a higher value if you have enough physical memory on your system by using below command the server
ALTER SYSTEM SET PGA_AGGREGATE_LIMIT=6000M SCOPE=BOTH;

No need restart the database, as this is a dynamic parameter.


==========================================
How to know if pga_aggregate_limit is set ot not?
==========================================
CREATE PFILE='/software/oracle/122/dbs/pfileigt.ora_20231121' FROM SPFILE='/software/oracle/122/dbs/spfileigt.ora';

oracle@qanfv-2-dbs-01:~>% less /software/oracle/122/dbs/pfileigt.ora_20231121 | grep -i pga

igt.__pga_aggregate_target=18790481920
*._pga_max_size=5368709120
*.pga_aggregate_target=15728640000


SQL> SHOW PARAMETER PGA_AGGREGATE

NAME                         VALUE
---------------------------- --------------
pga_aggregate_limit          56G
pga_aggregate_target         15000M

SQL> SHOW PARAMETER MEMORY
NAME                         VALUE
---------------------------- --------------
memory_max_target            56G
memory_target                50G


PGA_AGGREGATE_LIMIT Theory
PGA_AGGREGATE_LIMIT specifies a limit on the aggregate PGA memory consumed by the instance.

Default value
If MEMORY_TARGET is set, then PGA_AGGREGATE_LIMIT defaults to the MEMORY_MAX_TARGET value.

If MEMORY_TARGET is not set, then PGA_AGGREGATE_LIMIT defaults to 200% of PGA_AGGREGATE_TARGET.

If MEMORY_TARGET is not set, and PGA_AGGREGATE_TARGET is explicitly set to 0, then the value of PGA_AGGREGATE_LIMIT is set to 90% of the physical memory size minus the total SGA size.

In all cases, the default PGA_AGGREGATE_LIMIT is at least 2GB and at least 3MB times the PROCESSES parameter (and at least 5MB times the PROCESSES parameter for an Oracle RAC instance).

Range of values
Do not attempt to set PGA_AGGREGATE_LIMIT below its default value, even in a parameter file (pfile), or instance startup will fail. 
However, PGA_AGGREGATE_LIMIT can be set to 0 either in a parameter file or dynamically after startup. 
If a value of 0 is specified, it means there is no limit to the aggregate PGA memory consumed by the instance.

Tuesday, November 14, 2023

Gather stats from crontab - once a month

crontab (run at 22:05 on second of each month)
5 22 2 * * bash -l /software/oracle/oracle/scripts/shared_pool_latch/gather_stats.sh

gather_stats.sh
#!/bin/bash
ORA_VER=1120
ORACLE_SID=igt
ORACLE_BASE=/software/oracle
ORA_NLS33=/software/oracle/112/ocommon/nls/admin/data
ORACLE_HOME=/software/oracle/112
WORK_DIR=/software/oracle/oracle/scripts/shared_pool_latch
LOG_FILE=${WORK_DIR}/gather_stats.log
RUN_DATE=`date "+%Y%m%d"_"%H%M"`
cd $WORK_DIR
echo "===============================" >> ${LOG_FILE}
echo "Start Gather Stats at ${RUN_DATE}" >> ${LOG_FILE}
sqlplus / as sysdba @gather_stats.sql
RUN_DATE=`date "+%Y%m%d"_"%H%M"`
echo "Finished Gather Stats at ${RUN_DATE}" >> ${LOG_FILE}
echo "===============================" >> ${LOG_FILE}

gather_stats.sql
spool gather_stats.log append
PROMPT DBMS_STATS.GATHER_SCHEMA_STATS ('SYS')
BEGIN
 DBMS_STATS.GATHER_SCHEMA_STATS ('SYS');
END;
/
PROMPT DBMS_STATS.GATHER_DICTIONARY_STATS
BEGIN
 DBMS_STATS.GATHER_DICTIONARY_STATS;
END;
/
PROMPT DBMS_STATS.GATHER_FIXED_OBJECTS_STATS
BEGIN
 DBMS_STATS.GATHER_FIXED_OBJECTS_STATS;
END;
/
PROMPT DBMS_STATS.gather_schema_stats('XXX_YYYYY_AAAAA')
BEGIN
 DBMS_STATS.gather_schema_stats('XXX_YYYYY_AAAAA');
END;
/
PROMPT DBMS_STATS.gather_schema_stats('XXX_YYYYY_BBBBB')
BEGIN
 DBMS_STATS.gather_schema_stats('XXX_YYYYY_BBBBB');
END;
/
PROMPT DBMS_STATS.gather_schema_stats('XXX_YYYYY_CCCCC')
BEGIN
 DBMS_STATS.gather_schema_stats('XXX_YYYYY_CCCCC');
END;
/
EXIT;

Sunday, October 29, 2023

DBMS_STATS Starhome Stuff

BEGIN
 DBMS_STATS.GATHER_SCHEMA_STATS ('SYS');
END;
/

BEGIN
 DBMS_STATS.GATHER_DICTIONARY_STATS;
END;
/

BEGIN
 DBMS_STATS.GATHER_FIXED_OBJECTS_STATS;
END;
/


BEGIN
  DBMS_STATS.gather_table_stats
  (ownname=>'XXX', 
   tabname=>'GSM_IMSI_PREFIXES', 
   estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
   cascade => DBMS_STATS.AUTO_CASCADE );
END;
/

BEGIN
  DBMS_STATS.gather_table_stats
  (ownname=>'XXX', 
   tabname=>'GSM_COUNTRIES', 
   estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
   cascade => DBMS_STATS.AUTO_CASCADE );
END;
/

BEGIN
  DBMS_STATS.gather_table_stats
  (ownname=>'XXX', 
   tabname=>'GSM_NETWORKS_T', 
   estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
   cascade => DBMS_STATS.AUTO_CASCADE );
END;
/

BEGIN
  DBMS_STATS.gather_table_stats
  (ownname=>'XXX', 
   tabname=>'GSM_MERGE_NETWORKS', 
   estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
   cascade => DBMS_STATS.AUTO_CASCADE );
END;
/

BEGIN
  DBMS_STATS.gather_table_stats
  (ownname=>'XXX', 
   tabname=>'GSM_MERGE_NW_MAPPING', 
   estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
   cascade => DBMS_STATS.AUTO_CASCADE );
END;
/

BEGIN
  DBMS_STATS.gather_table_stats
  (ownname=>'XXX', 
   tabname=>'GSM_NETWORKS_SEG_T', 
   estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
   cascade => DBMS_STATS.AUTO_CASCADE );
END;
/

BEGIN
  DBMS_STATS.gather_table_stats
  (ownname=>'XXX', 
   tabname=>'GA_LANGUAGES', 
   estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
   cascade => DBMS_STATS.AUTO_CASCADE );
END;
/

BEGIN
  DBMS_STATS.gather_table_stats
  (ownname=>'XXX', 
   tabname=>'GSM_SERVICE_MERGED_NETWORKS', 
   estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
   cascade => DBMS_STATS.AUTO_CASCADE );
END;
/

BEGIN
  DBMS_STATS.gather_table_stats
  (ownname=>'XXX', 
   tabname=>'GSM_NETWORKS_EXCEPTIONS', 
   estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
   cascade => DBMS_STATS.AUTO_CASCADE );
END;
/

BEGIN
  DBMS_STATS.gather_table_stats
  (ownname=>'XXX', 
   tabname=>'GA_ACCOUNTS', 
   estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
   cascade => DBMS_STATS.AUTO_CASCADE );
END;
/

BEGIN
 DBMS_STATS.GATHER_SCHEMA_STATS( ownname => NULL);
END;
/


=========================
See execution plan of an SQL
=========================
ALTER SYSTEM FLUSH SHARED_POOL;

SELECT sql_id, child_number 
  FROM V$SQL 
WHERE sql_id = 'fw4tmpkt79r4r';

SELECT sql_id, child_number 
  FROM V$SQL 
WHERE sql_text LIKE 'MERGE into SGA_W_IPN_SUBSCRIBER o using%';


SET LINESIZE 120
SET PAGESIZE 0
SELECT * FROM TABLE(DBMS_XPLAN.display_cursor('fw4tmpkt79r4r',3,'OUTLINE'));


=========================
How to Flush a single SQL
=========================
--DBA_HIST_ACTIVE_SESS_HISTORY 
SELECT * FROM DBA_HIST_ACTIVE_SESS_HISTORY 
 WHERE sql_id IN ('ccgg2ap67ptbp','0gn14c20ay0qs') 
   AND SNAP_ID = (SELECT MAX(snap_id) from DBA_HIST_SNAPSHOT);

--V$SESSION
SELECT * FROM V$SESSION 
 WHERE sql_id IN ('ccgg2ap67ptbp','0gn14c20ay0qs');

--V$SQLAREA 
SELECT sql_text, sql_id, last_active_time, executions, 
       disk_reads, buffer_gets, user_io_wait_time
FROM V$SQLAREA 
WHERE sql_id IN ('ccgg2ap67ptbp','0gn14c20ay0qs');

--Flush Shared Pool for SQLs in question
SELECT 'EXEC DBMS_SHARED_POOL.PURGE ('''||ADDRESS||','||HASH_VALUE||''',''C'');' FROM  V$SQLAREA where SQL_Id='ccgg2ap67ptbp';
SELECT 'EXEC DBMS_SHARED_POOL.PURGE ('''||ADDRESS||','||HASH_VALUE||''',''C'');' FROM  V$SQLAREA where SQL_Id='0gn14c20ay0qs';

SQL> EXEC DBMS_SHARED_POOL.PURGE ('00000000FD2BC510,1283122549','C');

PL/SQL procedure successfully completed.

SQL> EXEC DBMS_SHARED_POOL.PURGE ('000000009A0252B8,2158953176','C');

PL/SQL procedure successfully completed.