Pages

Monday, June 16, 2014

Perl by example. get file with FTP, read file line by line, load contents to DB.

General
The flow of events is:
- Get file by FTP.
- Read the file line by line
- Parse each line into fields
- Load content, line by line, into DB

The files:
launch_load_counters.bat
load_counters.pl

launch_load_counters.bat
perl load_counters.pl

load_counters.pl
#! /usr/bin/perl
use DBI;
use Net::FTP;
use Time::gmtime;
use File::Copy;

#-----------------------------
# get 15 minutes interval ID
#-----------------------------
sub CalcInterval
{
 local($hour,$minute)=($_[0],$_[1]);
 my $intid=(($hour*3600)+($minute*60))/900;
 if ($intid == 0)
 {
   $intid=95
 }
 else
 {
   $intid=$intid-1;
 }
 return $intid;
}

#-----------------------------
# get Current Date
#-----------------------------
sub getDate
{
  use Time::gmtime;
  $tm=gmtime;
  ($day,$month,$year) = (gmtime) [3,4,5];
  my $locDate=sprintf("%04d%02d%02d",$tm->year+1900,($tm->mon)+1,$tm->mday);
  return $locDate;
}

#-----------------------------
# get Current Time
#-----------------------------
sub getTime
{
 use Time::gmtime;
 $lt=gmtime;
 ($hour,$minute,$seconds)=(gmtime) [1,2];
 my $LocTime = sprintf ("%02d%02d%02d",$lt->hour,$lt->min,$lt->sec);
 return $LocTime
}

#----------------------------------
sub GetCounterFile
#----------------------------------
{
  my $home_dir="d:\\COUNTERS";
  my $newerr=0;
  my $logDate= getDate;
  my $logTime= getTime;
  my $CounterFile;

  #for debug messages- set to 1 
  my $debugInd=1;
  #for using test file set to 1 
  my $loadTestData=0;
  
  if ($debugInd==1){
    my $log_file = $home_dir."\\"."counters\\Get_Counter_File".$logDate."_".$logTime.".log";  
    open MyFtpLogFile,">>".$log_file;
    print MyFtpLogFile "start MyFtpLogFile for :".$logDate."_".$logTime."\n";   
  }
  
  if ($loadTestData==1){
    $CounterFile = "test_counters.txt";
  }else{
    $CounterFile = "OutCounters.txt.fin";
  }
  
  if ($debugInd==1){print MyFtpLogFile "Loading from file ".$CounterFile."\n";}
  
  
  my $OrigCounterFile = "OutCounters.txt";
  my $LocCounterDir=$home_dir."\\"."counters";
  my $ScriptDir =$home_dir."\\"."scripts\\";
  my $CounterBckDir = $home_dir."\\"."counters\\old_counters_files\\";

  my $address = "000.000.000.000";
  my $username="user";
  my $pass="pass";
  my $rem_dir="counters/";
  
  my $PDate=getDate;
  my $PTime=getTime;
  if ($debugInd==1){print MyFtpLogFile "Before chdir(".$LocCounterDir.")"."\n";}
  
  chdir($LocCounterDir);
  if ($debugInd==1){print MyFtpLogFile "After chdir(".$LocCounterDir.")"."\n";}
  
  
  $ftp=Net::FTP->new($address,Timeout=>240) or die "Cant FTP to host" ;  
  if ($debugInd==1){print MyFtpLogFile "After opening ftp connection"."\n";}
  
  
  $ftp->login($username,$pass) or die "Cant login to host";  
  if ($debugInd==1){print MyFtpLogFile "After ftp login"."\n";}
  
  
  $ftp->cwd($rem_dir) or die "Cant cd to remote directory";
  $ftp->pwd or die "Cant pwd";
  if ($debugInd==1){print MyFtpLogFile "After cd to remote directory ".$rem_dir."\n";}
  
  
  $ftp->binary;  
  if ($debugInd==1){print MyFtpLogFile "After set ftp mode to binary"."\n";}
  if ($debugInd==1){print MyFtpLogFile "Before ftp get ".$CounterFile."\n";}
  
  $ftp->get($CounterFile,$CounterFile) or $newerr=1;
  
  if ($debugInd==1){
    print MyFtpLogFile "Got file from server: ".$CounterFile."\n";  
    print MyFtpLogFile "FTP return status=".$newerr."\n";
    if ($newerr==1){
       print MyFtpLogFile "----E---- "."Cannot get file ".$CounterFile." from remote Directory: ".$rem_dir."\n";
       $ftp->quit;
       return 0;
    }
  }
  
  $ftp->rename($CounterFile,$CounterFile.$PDate.$PTime);
  if ($debugInd==1){print MyFtpLogFile "After ftp rename from ".$CounterFile." to ".$CounterFile.$PDate.$PTime."\n";}
  
  $ftp-> quit;
  move($CounterFile,$OrigCounterFile);
  if ($debugInd==1){
    print MyFtpLogFile "After local rename from ".$CounterFile." to ".$OrigCounterFile."\n";
    print MyFtpLogFile $OrigCounterFile." file created under folder: ".$LocCounterDir."\n"; 
    close(MyFtpLogFile); 
  }
  
  chdir($ScriptDir);
  return 1;
}

sub LoadCounterFile
{
   #declare variables
   my $home_dir="d:\\COUNTERS";
   my $customer_id="001";
   my $DateOfCall;
   my $DayOfCall;
   my $processName="";
   my $IntervalID;
   my $LocCounterDir=$home_dir."\\"."counters\\";
   my $OrigCounterFile= "OutCounters.txt";
   my $logDate= getDate;
   my $logTime= getTime;
   
   #for debug set debugInd to 1
   my $debugInd=1;
   #to skip load to db set debugSkipLoadToDbInd to 1
   my $debugSkipLoadToDbInd=0;
   
   if ($debugInd==1){
     my $log_file = $home_dir."\\"."counters\\Load_Counters".$logDate."_".$logTime.".log";
     open MyLoadCountersLogFile,">>".$log_file;
     print MyLoadCountersLogFile "Start Loading Counters for :".$logDate."_".$logTime."\n";    
     print MyLoadCountersLogFile "Before opening DB connection"."\n";   
   }
   ##Connect to the db
   my $dbh=DBI->connect('dbi:Oracle:sid','user','passwd',{RaiseError =>1,AutoCommit=>0})||die "$DBI::errstr";
   print $DBI::errstr;
   
   if ($debugInd==1){
     print MyLoadCountersLogFile "The DBI:err: ".$DBI::errstr."\n";      
     print MyLoadCountersLogFile "After opening DB connection"."\n";
     print MyLoadCountersLogFile "Before opening Counters File ".$LocCounterDir.$OrigCounterFile."\n";  
  print MyLoadCountersLogFile "Running in mode debugSkipLoadToDbInd=".$debugSkipLoadToDbInd."\n";  
   }
   
   ##read the file and prepare the insets   
   open(MyCountFile,$LocCounterDir.$OrigCounterFile) or die("Cannot open file ".$LocCounterDir.$OrigCounterFile);   
   @DataLine = <MyCountFile>;
   close(MyCountFile);

   if ($debugInd==1){print MyLoadCountersLogFile "After opening  MyCountFile ".$LocCounterDir.$OrigCounterFile."\n";}
   
   ##use the data
   foreach $Dline (@DataLine)
   {
     print MyLoadCountersLogFile "Starting Loading line ".$Dline."\n";
     chomp($Dline);

       ($field0,$field1,$field2,$field3,$field4,$field5,$field6,$field7,$field8,$field9,$field10)=split(/\,/,$Dline);
 $IntervalID=CalcInterval($field1,$field2);
 $DayOfCall=substr($field0,6,2);
 $nowDate=getDate;
 $nowTime=getTime;
 $lastUpdateTime=$field0.$field1.$field2;
 if ($field4=="NA"){$field4=0; }
 if ($field5=="NA"){$field5=0; }
 if ($field6=="NA"){$field6=0; }
 if ($field7=="NA"){$field7=0; }
 if ($field8=="NA"){$field8=0; }
 if ($field9=="NA"){$field9=0; }
 if ($field10=="NA"){$field10=0; }
   
  my $sql = qq{insert into counter_data (customer_id,day_of_call,counter_id,counter_name,interval_id,counter_sum,counter_delta,date_of_call) values(?,?,?,?,?,?,?,?)};
  my $sth=$dbh->prepare($sql);
  $sth->execute ($customer_id,$DayOfCall,2002,"COUNTER_1",$IntervalID,0,$field4,$field0);
  if ($debugInd==1){print MyLoadCountersLogFile "Loading COUNTER_1 line "."\n";}
  if ($debugSkipLoadToDbInd==1){
    $dbh->rollback;
  }else{
    $dbh->commit;
  }     
  $sth->finish();

  my $sql = qq{insert into counter_data (customer_id,day_of_call,counter_id,counter_name,interval_id,counter_sum,counter_delta,date_of_call) values(?,?,?,?,?,?,?,?)};
  my $sth=$dbh->prepare($sql);
  $sth->execute ($customer_id,$DayOfCall,2003,"COUNTER_2",$IntervalID,0,$field5,$field0);
  if ($debugInd==1){print MyLoadCountersLogFile "Loading COUNTER_2 line "."\n";}
  if ($debugSkipLoadToDbInd==1){  
    $dbh->rollback;
  }else{
    $dbh->commit;
  }     
  $sth->finish();

  my $sql = qq{insert into counter_data (customer_id,day_of_call,counter_id,counter_name,interval_id,counter_sum,counter_delta,date_of_call) values(?,?,?,?,?,?,?,?)};
  my $sth=$dbh->prepare($sql);
  $sth->execute ($customer_id,$DayOfCall,2004,"COUNTER_3",$IntervalID,0,$field6,$field0);
  if ($debugInd==1){print MyLoadCountersLogFile "Loading COUNTER_3 line "."\n";}
  if ($debugSkipLoadToDbInd==1){
    $dbh->rollback;
  }else{
    $dbh->commit;
  }     
  $sth->finish();

  my $sql = qq{insert into counter_data (customer_id,day_of_call,counter_id,counter_name,interval_id,counter_sum,counter_delta,date_of_call) values(?,?,?,?,?,?,?,?)};
  my $sth=$dbh->prepare($sql);
  $sth->execute ($customer_id,$DayOfCall,2009,"COUNTER_4",$IntervalID,0,$field7,$field0);
  if ($debugInd==1){print MyLoadCountersLogFile "Loading COUNTER_4 line "."\n";}
  if ($debugSkipLoadToDbInd==1){
    $dbh->rollback;
  }else{
    $dbh->commit;
  }     
  $sth->finish();

  my $sql = qq{insert into counter_data(customer_id,day_of_call,counter_id,counter_name,interval_id,counter_sum,counter_delta,date_of_call) values(?,?,?,?,?,?,?,?)};
  my $sth=$dbh->prepare($sql);
  $sth->execute ($customer_id,$DayOfCall,3001,"COUNTER_5",$IntervalID,0,$field8,$field0);
  if ($debugInd==1){print MyLoadCountersLogFile "Loading COUNTER_5 line "."\n";}
  if ($debugSkipLoadToDbInd==1){
    $dbh->rollback;
  }else{
    $dbh->commit;
  }     
  $sth->finish();

  my $sql = qq{insert into counter_data (customer_id,day_of_call,counter_id,counter_name,interval_id,counter_sum,counter_delta,date_of_call) values(?,?,?,?,?,?,?,?)};
  my $sth=$dbh->prepare($sql);
  $sth->execute($customer_id, $DayOfCall, 3003, "COUNTER_6", $IntervalID,0,$field9,$field0);
  if ($debugInd==1){print MyLoadCountersLogFile "Loading COUNTER_6 line "."\n";}
  if ($debugSkipLoadToDbInd==1){
    $dbh->rollback;
  }else{
    $dbh->commit;
  }     
  $sth->finish();

  $field10=~ s/\D+//g;

  my $sql = qq{insert into counter_data (customer_id,day_of_call,counter_id,counter_name,interval_id,counter_sum,counter_delta,date_of_call) values(?,?,?,?,?,?,?,?)};
  my $sth=$dbh->prepare($sql);
  $sth->execute ($customer_id,$DayOfCall,3006,"COUNTER_7",$IntervalID,0,$field10,$field0);
  if ($debugInd==1){print MyLoadCountersLogFile "Loading COUNTER_6 line "."\n";}
  if ($debugSkipLoadToDbInd==1){
    $dbh->rollback;
  }else{
    $dbh->commit;
  }     
  $sth->finish();

  if ($debugInd==1){
    print MyLoadCountersLogFile "Finished Loading line ".$Dline."\n";
  }
 }
 if ($debugInd==1){
    print MyLoadCountersLogFile "Load Counters to DB Completed"."\n";  
    close(MyLoadCountersLogFile); 
 }   
 return 1;
}

#---------------
#main()
#---------------
#declare variables
my $home_dir="d:\\COUNTERS";
my $log_file = $home_dir."\\"."counters\\ProcessLog.txt";
my $logDate= getDate;
my $logTime= getTime;

open MyLogFile,">>".$log_file;
print MyLogFile "Start Process for: ".$logDate."_".$logTime."\n";

#get the counter file by ftp
GetCounterFile;
print MyLogFile "After FTP get counters....";

#Load the counters into the db
LoadCounterFile;
print MyLogFile "After LoadCounters..."."\n";

my $targetFile = $home_dir."\\"."counters\\old_counters_files\\OutCounters.txt".$logDate.$logTime;
move($home_dir."\\"."counters\\OutCounters.txt",$targetFile);
print MyLogFile "New File Created: ".$targetFile."\n";
print MyLogFile "End Process for: ".$logDate."_".$logTime."\n\n";
exit 0;

Thursday, June 12, 2014

Create AWR Daily Report and Weekly Report run by crontab

General
  One of the most useful tasks for a DBA is to have an up to date summery of current activity in DB, including top SQLs, Disk IO usage, etc.
  One of the way to do that, is to have AWR Report Generated on an ongoing basis.

Steps
Setup AWR Retention Policy.
Create a bash script to run AWR Report.
Create a crontab task to automate AWR Report executions.

Setup AWR Retention Policy.
1. Check current retention poilicy.
SELECT
(EXTRACT( DAY FROM SNAP_INTERVAL) *24*60+ EXTRACT( HOUR FROM SNAP_INTERVAL) *60+ EXTRACT( MINUTE FROM SNAP_INTERVAL ))/60 AS "Snapshot Interval (Hour)",
(EXTRACT( DAY FROM RETENTION) *24*60+  EXTRACT( HOUR FROM RETENTION) *60+ EXTRACT( MINUTE FROM RETENTION ))/(24*60) AS "Retention Interval (Days)"
FROM DBA_HIST_WR_CONTROL;

------------------------ -------------------------
                       1                         7

By default snapshots are taken every hour and retained for 7 days.
To change the default settings, use DBMS_WORKLOAD_REPOSITORY.modify_snapshot_settings:

BEGIN
  DBMS_WORKLOAD_REPOSITORY.modify_snapshot_settings(
    retention => 43200,  -- Minutes (= 30 Days). Current value retained if NULL.
    interval  => 30);    -- Minutes. Current value retained if NULL.
END;
/

Create a bash script to run AWR Report.
Oracle provides sql scripts to generate AWR report, either in text or html format.
@$ORACLE_HOME/rdbms/admin/awrrpt.sql

Oracle awrrpt.sql script, requires runtime parameters input - such as report format, report file name, Begin snapshot ID, End snapshot ID.

The script below, provided sets the required input parameter values, and wraps the call to awrrpt.sql.

Flow of events:
cron is starting task: generate_awr_daily.sh or generate_awr_weekly.sh
generate_awr_daily.sh or generate_awr_weekly.sh call generate_awr.sh
generate_awr.sh calls generate_awr.sql
generate_awr.sql set all AWR report parameters, and calls Oracle awrrpt.sql.


create directoriesmkdir_for_awr.sh
#!/bin/bash
mkdir -p /software/oracle/oracle/.scripts/AWR/script
mkdir -p /software/oracle/oracle/.scripts/AWR/history


crontab entry
> crontab -l
00 05 * * *   . $HOME/.profile_for_awr; /somepath/userA/AWR_FILES/code/generate_awr_daily.sh  &>/somepath/userA/AWR_FILES/logs/daily_awr.log
01 05 * * 4 . $HOME/.profile_for_awr; /somepath/userA/AWR_FILES/code/generate_awr_weekly.sh &>/somepath/userA/AWR_FILES/logs/weekly_awr.log


The crontab file is at: /var/spool/cron
-rw-------  1 root groupA 258 May 29 13:36 userA
-rw-------  1 root groupA 235 Jun 21  2006 userB

A note about crontab entry:
A. Schedule

# Minute   Hour   Day of Month  Month             Day of Week      Command    
# (0-59)  (0-23)  (1-31)        (1-12 or Jan-Dec) (0-6 or Sun-Sat)                

  0        2      12            *                 *                /usr/bin/find

B. Envirnment Variables.
The crontab task creation is pretty much straight forward.
The only tweak is setting the environment variables.


cron knows nothing about your shell.
It is started by the system, so it has a minimal environment. 
Thus need to set the environment variables before running the script, by:
 . $HOME/.profile_for_awr;
Note the ";" at the end of the source command.

Another option would be to set environment variables from inside the shell script.

export ORACLE_HOME=/software/oracle/122
export ORACLE_BASE=/software/oracle
export ORACLE_SID=orasid
export ORA_VER=1220
export ORA_BIN=${ORACLE_HOME}/bin

export PATH=$PATH:$ORA_BIN


In this example:
generate_awr_daily.sh script is running every day, at 00 minutes, 05AM.
generate_awr_weekly.sh script is running once a week, at 01 minutes, 05AM on Thursday.
Before script execution, that $HOME/.bash_profile is sourced.
The job activity is logged to /starhome/iu/AWR_FILES/logs/daily_awr.log.

generate_awr_hourly.sh
#!/bin/bash

export AWR_HOME=/software/oracle/oracle/.scripts/AWR/script
export AWR_OUTPUT=/software/oracle/oracle/.scripts/AWR/history
export ORACLE_SID=igt
NUM_OF_DAYS=1
INSTANCE_NAME=igt
KEEP_DAYS=7

cd $AWR_HOME

./generate_awr.sh system Xen86Pga igt $NUM_OF_DAYS $INSTANCE_NAME

mv ${AWR_HOME}/AWR* ${AWR_OUTPUT}/
find ${AWR_OUTPUT}/AWR* -mtime +${KEEP_DAYS} -exec rm {} \;
exit 0

generate_awr_daily.sh
#!/bin/bash

export AWR_HOME=/software/oracle/oracle/.scripts/AWR/script
export AWR_OUTPUT=/software/oracle/oracle/.scripts/AWR/history
export ORACLE_SID=igt
NUM_OF_DAYS=1
INSTANCE_NAME=igt
KEEP_DAYS=7

cd $AWR_HOME

./generate_awr.sh system Xen86Pga igt $NUM_OF_DAYS $INSTANCE_NAME

mv ${AWR_HOME}/AWR* ${AWR_OUTPUT}/
find ${AWR_OUTPUT}/AWR* -mtime +${KEEP_DAYS} -exec rm {} \;
exit 0


generate_awr_weekly.sh
#!/bin/bash

export AWR_HOME=/software/oracle/oracle/.scripts/AWR/script
export AWR_OUTPUT=/software/oracle/oracle/.scripts/AWR/history
export ORACLE_SID=igt
NUM_OF_DAYS=7
INSTANCE_NAME=igt
KEEP_DAYS=7

cd $AWR_HOME

./generate_awr.sh system Xen86Pga igt $NUM_OF_DAYS $INSTANCE_NAME

mv ${AWR_HOME}/AWR* ${AWR_OUTPUT}/
find ${AWR_OUTPUT}/AWR* -mtime +${KEEP_DAYS} -exec rm {} \;
exit 0

generate_awr.sh
#!/bin/bash

USER=$1
PASS=$2
SID=$3
NUM_OF_DAYS=$4
INSTANCE_NAME=$5

sqlplus -S ${USER}/${PASS}@${SID} << EOF
@generate_awr.sql $NUM_OF_DAYS $INSTANCE_NAME
exit;
EOF


generate_awr.sql
DEFINE num_days=&1;
DEFINE i_instance=&2;

DEFINE inst_name='';
DEFINE report_type='html';
DEFINE report_name='';
DEFINE begin_snap=0;
DEFINE end_snap=0; 

column inst_name  heading "Instance Name" new_value inst_name format A16;
SELECT UPPER('&i_instance') inst_name FROM DUAL;

column begin_snap heading "Min SNAP ID"  new_value begin_snap format 9999999999;
column end_snap heading "Max SNAP ID"  new_value end_snap format 9999999999;

------------------------
--For Daily Report
------------------------ SELECT MIN(SNAP_ID) begin_snap FROM dba_hist_snapshot WHERE TRUNC(begin_interval_time) = TRUNC(SYSDATE-&num_days);
SELECT MAX(SNAP_ID) end_snap FROM dba_hist_snapshot WHERE TRUNC(begin_interval_time) = TRUNC(SYSDATE-&num_days);
------------------------
--For Hourly Report
------------------------
SELECT MAX(SNAP_ID)-1 begin_snap FROM dba_hist_snapshot;
SELECT MAX(SNAP_ID)   end_snap FROM dba_hist_snapshot;

column report_name heading "AWR file name"  new_value report_name format A30; 
SELECT 'AWR'||'_'||'&inst_name'||'_'||DECODE(&num_days,1,'Daily',7,'Weekly','Unknown Period')||'_'||TO_CHAR(SYSDATE,'YYYYMMDD_hhmmss')||'.'||'&report_type' report_name FROM DUAL; 


SELECT &num_days num_days FROM DUAL;
SELECT '&report_type'   report_type FROM DUAL;
SELECT '&report_name'   report_name FROM DUAL;
SELECT &begin_snap begin_snap FROM DUAL;
SELECT &end_snap end_snap FROM DUAL;

@@/software/oracle/122/rdbms/admin/awrrpt.sql

undefine num_days;
undefine report_type;
undefine report_name;
undefine begin_snap;

undefine end_snap;

crontab quick reference
Entry example:
00 05 * * *   . $HOME/.profile_for_awr; 

00 - min. 00-59
05 - hour. 00-23
* - Day of month. 1-31
* - Month. 1-12
* - Day of week (0 - 6) (Sunday=0)


Remove multiple files, older than 5 days with one command from crontab
15 23 * * * find . -type f -name "FILE-TO-FIND" -mtime +5 -exec rm -rf {} \;



Simple script to generate AWR
.set_profile
export ORACLE_HOME=/software/oracle/111
export ORACLE_SID=igt

export PATH=$PATH:/software/oracle/111/bin

.generate_awr.sh
#!/bin/bash

. .set_profile

sqlplus system/xen86pga@igt @/software/oracle/111/rdbms/admin/awrrpt.sql


Appendix
AWR Retention period sizing guidelines
Automatic Workload Repository (AWR) in Oracle Database 10g
Crontab – Quick Reference

Wednesday, June 11, 2014

Batch script by example. Scheduled task that calls batch file, that calls ftp script.

General
This is an example, of creating a scheduled task, on Windows, that would do ftp files to another server.

Flow
1. Get File from Linux server
2. Move it to Windows
3. Handle Files (get last file, delete old files, etc)
4. Send mail, using blat utility

Files
A. main_awr_daily.bat - The main script. Call all other scripts one after another.

B. get_awr_report.bat using ftp_daily_awr_cmd.ini - Get file with ftp from Linux server.

C. delete_old_awr_files.bat - Delete old files from Windows server.

D. mail_report_main.bat - Send the report with blat utility.

main_awr_daily.bat
ECHO OFF

SET SERVER=some.server.com
SET USER=user

SET STEP=get_awr_report.bat 
ECHO Calling %STEP%
call get_awr_report.bat %USER% %SERVER%  ftp_daily_awr_cmd.ini
ECHO Finished %STEP%
ECHO.

SET STEP=delete_old_awr_files.bat
ECHO Calling %STEP%
call delete_old_awr_files.bat J:\Functionality\AWR\Files AWR_*_Daily* 10
ECHO Finished %STEP%
ECHO.

SET STEP=mail_report_main.bat
ECHO Calling %STEP%
call mail_report_main.bat J:\Functionality\AWR\Files AWR_*_Daily* "AWR Daily Report" mail_awr_daily_header.txt
ECHO Finished %STEP%
ECHO.

get_awr_report.bat
SET USER=%1
SET SERVER=%2
SET PARAM_FILE=%3
sftp -b %PARAM_FILE% %USER%@%SERVER%

ftp_daily_awr_cmd.ini
lcd J:\Functionality\AWR\Files
cd /starhome/iu/AWR_FILES/files
mget AWR*Daily*
bye


delete_old_awr_files.bat
ECHO OFF
SET HOME_DIR=%1
SET FILES_FILTER=%2
SET RETENTION_DAYS=%3

REM Delete files older than 10 days
forfiles /P %HOME_DIR% /M %FILES_FILTER% /C "cmd /c del @file" /D -%RETENTION_DAYS%

REM For test 
REM goto FINISH
REM :FINISH
REM pause

mail_report_main.bat
ECHO OFF
SET WORK_PATH=%1
SET FILE_FILTER=%2
SET MAIL_SUBJECT=%3
SET MAIL_BODY=%4

ECHO Looking for Last File in %WORK_PATH%\%FILE_FILTER%
for /f "tokens=*" %%i in ('dir %WORK_PATH%\%FILE_FILTER% /b/a-d/od/t:c') do set LAST_FILE=%%i
ECHO Last File: %LAST_FILE%

for %%i in (%LAST_FILE%) do set LAST_FILE_NAME=%%~nxi
call mail_report.bat %WORK_PATH%\%LAST_FILE% %LAST_FILE_NAME% %MAIL_SUBJECT% %MAIL_BODY%

mail_report.bat
SET SOURCE_FILE=%1
SET SEND_FILE=%2
SET SUBJECT=%3
SET MAIL_BODY=%4

ECHO copy %SOURCE_FILE% %SEND_FILE%
copy %SOURCE_FILE% %SEND_FILE%

echo about to mail file %SEND_FILE% -to to_userA@domain.com, to_userB@domain.com -i from_user@domain.com -subject %SUBJECT%
blat %MAIL_BODY% -to to_userA@domain.comto_userB@domain.com -i from_user@domain.com -subject %SUBJECT% -attacht %SOURCE_FILE% 

sleep 2

del %SEND_FILE%

mail_awr_daily_header.txt
Hi,
   Please see attached Daily AWR Report.

  

Oracle Memory Issues. Dealing with ORA-04031: unable to allocate 4032 bytes of shared memory and ORA-04030: out of process memory when trying to allocate bytes

ORA-04031: unable to allocate 4032 bytes of shared memory

Background
Since Oracle 11 - Memory management is done via setting one parameter: memory_max_target
By default setting, memory_max_target effect the whole SGA memory size. 
Oracle divides that memory between the various memory areas: Shared Pool, Java Pool, Large Object Pool.

How to see current memory

set linesize 120

show parameter memory

NAME                                 TYPE        VALUE
------------------------------------ ----------- --------
hi_shared_memory_address             integer     0
memory_max_target                    big integer 500M
memory_target                        big integer 500M
shared_memory_address                integer     0  

OR

SQL> SELECT * FROM V$VERSION;


BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
PL/SQL Release 11.1.0.7.0 - Production
CORE    11.1.0.7.0      Production
TNS for Linux: Version 11.1.0.7.0 - Production
NLSRTL Version 11.1.0.7.0 - Production

shared_memory_address                    0
shared_pool_reserved_size                10276044
shared_pool_size                         0
memory_max_target                        524288000
memory_target                            524288000
java_pool_size                           0
large_pool_size                          0

OR

SQL> SELECT NAME, VALUE FROM V$PARAMETER WHERE name like '%memo%'


Resolution
Several options, as the reasons for ORA-04031 may vary.

A. - Increase Oracle Memory

To increase the memory, need to reset memory_target and restart Oracle:
1.  ALTER SYSTEM SET MEMORY_MAX_TARGET = nM SCOPE = SPFILE;
2. STARTUP [FORCE]
3.  ALTER SYSTEM SET MEMORY_TARGET = nM;

STARTUP FORCE - If the database is open, then FORCE shuts down the database with a SHUTDOWN ABORT statement before re-opening it. If the database is closed, then FORCE opens the database.

By Example:

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

System altered.

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

SQL> STARTUP;
ORACLE instance started.

Total System Global Area 2087780352 bytes
Fixed Size                  2254824 bytes
Variable Size            1962936344 bytes
Database Buffers          117440512 bytes
Redo Buffers                5148672 bytes
Database mounted.
Database opened.

SQL> ALTER SYSTEM SET MEMORY_TARGET=2000M;


System altered.

B. - Flash Shared Pool
How to Flush Shared Pool
Option A - ALTER SYSTEM FLUSH SHARED_POOL;

ALTER SYSTEM FLUSH SHARED_POOL;

Option B - (from Oracle 11) - Flush only single object from Shared Pool.
DBMS_SHARED_POOL.PURGE(address||','||hash_value, 'C');
Where address and hash_value are retrieved from V$SQL.
'C' - Stands for Cursor.
See complete reference for DBMS_SHARED_POOL package: Oracle Reference.

C. - Restart server.
On Win 2003 server, from time to time server experiance memory leak issues, becomming extremely slow and unresponsive.
Reboot to Win server resolved the issue.

Evidences:
Alert.log:
Sun Mar 19 03:04:55 2017
Errors in file d:\software\oracle\diag\rdbms\igt\igt\trace\igt_ora_6056.trc  (incident=67969):
ORA-04031: unable to allocate 3936 bytes of shared memory ("shared pool","unknown object","sga heap(1,0)","kglsim object batch")
Sun Mar 19 03:05:12 2017
Errors in file d:\software\oracle\diag\rdbms\igt\igt\trace\igt_ora_6056.trc  (incident=67970):
ORA-04031: unable to allocate 3936 bytes of shared memory ("shared pool","unknown object","sga heap(1,0)","kglsim object batch")
Sun Mar 19 03:05:49 2017
Errors in file d:\software\oracle\diag\rdbms\igt\igt\trace\igt_ora_5740.trc  (incident=67969):
ORA-04031: unable to allocate 3936 bytes of shared memory ("shared pool","unknown object","sga heap(1,0)","kglsim object batch")
Sun Mar 19 03:06:17 2017
Errors in file d:\software\oracle\diag\rdbms\igt\igt\trace\igt_ora_5740.trc  (incident=67970):
ORA-04031: unable to allocate 3936 bytes of shared memory ("shared pool","unknown object","sga heap(1,0)","kglsim object batch")
Sun Mar 19 03:07:15 2017
Errors in file d:\software\oracle\diag\rdbms\igt\igt\trace\igt_ora_2628.trc  (incident=67969):
ORA-04031: unable to allocate 3936 bytes of shared memory ("shared pool","unknown object","sga heap(1,0)","kglsim object batch")
Sun Mar 19 03:07:32 2017
Errors in file d:\software\oracle\diag\rdbms\igt\igt\trace\igt_ora_2628.trc  (incident=67970):
ORA-04031: unable to allocate 3936 bytes of shared memory ("shared pool","unknown object","sga heap(1,0)","kglsim object batch")
Sun Mar 19 03:10:08 2017
DDE: Problem Key 'ORA 4031' was completely flood controlled (0x6)
Further messages for this problem key will be suppressed for up to 10 minutes
Sun Mar 19 03:19:51 2017
Errors in file d:\software\oracle\diag\rdbms\igt\igt\trace\igt_j001_6056.trc:
ORA-12012: error on auto execute of job 11285
ORA-04031: unable to allocate 3936 bytes of shared memory ("shared pool","DELETE FROM SYS.SCHEDULER$_J...","sga heap(1,0)","kglsim object batch")
ORA-06512: at "SYS.DBMS_ISCHED", line 566
ORA-06512: at "SYS.DBMS_SCHEDULER", line 
...
...
There are many incident files.
Sun Mar 19 03:55:07 2017
Errors in file d:\software\oracle\diag\rdbms\igt\igt\trace\igt_mmon_400.trc  (incident=70073):
ORA-04030: out of process memory when trying to allocate 123404 bytes (QERHJ hash-joi,kllcqas:kllsltba)
Incident details in: d:\software\oracle\diag\rdbms\igt\igt\incident\incdir_70073\igt_mmon_400_i70073.trc
Sun Mar 19 03:55:14 2017
Trace dumping is performing id=[cdmp_20170319035514]
Errors in file d:\software\oracle\diag\rdbms\igt\igt\trace\igt_mmon_400.trc  (incident=70074):
ORA-04030: out of process memory when trying to allocate ORA-04030: out of process memory when trying to allocate 123404 bytes (QERHJ hash-joi,kllcqas:kllsltba)
 bytes (,)
Incident details in: d:\software\oracle\diag\rdbms\igt\igt\incident\incdir_70074\igt_mmon_400_i70074.trc
Sun Mar 19 03:55:17 2017
Errors in file d:\software\oracle\diag\rdbms\igt\igt\trace\igt_ora_5732.trc  (incident=68171):
ORA-04030: out of process memory when trying to allocate 32784 bytes (pga heap,kgh stack)
Incident details in: d:\software\oracle\diag\rdbms\igt\igt\incident\incdir_68171\igt_ora_5732_i68171.trc
Sun Mar 19 03:55:18 2017
Starting background process CJQ0





Sun Mar 19 05:11:09 2017
Stopping background process CJQ0
Sun Mar 19 05:15:33 2017
Errors in file d:\software\oracle\diag\rdbms\igt\igt\trace\igt_mmon_400.trc  (incident=70075):
ORA-04030: out of process memory when trying to allocate 16396 bytes (QERHJ hash-joi,QERHJ Bit vector)
ORA-04030: out of process memory when trying to allocate ORA-04030: out of process memory when trying to allocate 123404 bytes (QERHJ hash-joi,kllcqas:kllsltba)
 bytes (,)
Incident details in: d:\software\oracle\diag\rdbms\igt\igt\incident\incdir_70075\igt_mmon_400_i70075.trc
Sun Mar 19 05:15:37 2017
Trace dumping is performing id=[cdmp_20170319051537]
Errors in file d:\software\oracle\diag\rdbms\igt\igt\trace\igt_mmon_400.trc  (incident=70076):
ORA-04030: out of process memory when trying to allocate ORA-04030: out of process memory when trying to allocate 16396 bytes (QERHJ hash-joi,QERHJ Bit vector)
ORA-04030: out of process memory when trying to allocate ORA-04030: out of process memory when trying to allocate 123404 bytes (QERHJ hash-joi,kllcqas:kllsltba)
 bytes (,)





Appendix
A. Oracle 11 Memory Architecture
B. Using Automatic Memory Management
C. Memory Target Wiki