Friday, December 18, 2009

HTML space report

Have you ever received a request from the Business people about the space usage of a database to be delivered to their inboxes on a daily basis, well yup, I did and since it had come from some one in real high authority - I decided to generate a pleasant report of the usage of database.

I wrote a shell script that has an in-built sql script which retrieves information from the dba_* views. This result is spooled as an html file and sent to the recipient(s) as an attachment. The shell script takes the ORACLE_SID (database name) as the command line argument. Please review the script once after pasting it into your editor of choice for editting/spacing errors.




####################################################
# Name : space_report.ksh
#
# Usage : ksh space_report.ksh ORACLE_SID
#
####################################################

#!/usr/bin/ksh

if [ "$#" -lt 1 ]
then
echo " \nUsage : ksh space_report.ksh ORACLE_SID "
echo "\n"
exit 1
fi

export ORATAB=/var/opt/oracle/oratab ## change this per your env.
export date_string=`date '+%d-%b-%Y'`
export ORACLE_SID=$1
export ORACLE_HOME=`grep $ORACLE_SID $ORATAB|head -1|awk -F":" '{print $2}'`
export To_id=to_id@oracleandunix.blogspot.com
export Cc_id=cc_id@oracleandunix.blogspot.com
export LOG_DIR=$HOME
export LOG_FILE=$LOG_DIR/${ORACLE_SID}_space_report_${date_string}.html
export CAP_ORACLE_SID=`echo $ORACLE_SID|tr [:lower:] [:upper:]`


$ORACLE_HOME/bin/sqlplus -S "/as sysdba" << E_O_F

set markup html on
spool $LOG_FILE
set pages 50
set lines 100
set echo off
set serveroutput on
set feed off
col "TABLESPACE" format a25
col "FREE" format 9999999.99
col "MAX_FREE" format 9999999.99
col "NEXT_EXT" format a8
col "% Full" format 9999
col TOTAL format 999999.99
col USED format 999999.99
col SIZE format 9999.99

select name "DB NAME", to_char(sysdate,'DD-MON-YYYY HH24:MI:SS') "REPORT RUN TIME"
from v$database;
prompt
prompt
select substr(t.tablespace_name,1,25) "TABLESPACE",
decode(b.EXTENT_MANAGEMENT,'LOCAL','L','DICTIONARY','D',b.EXTENT_MANAGEMENT)
"EXT MGMT",
t.totspace/1024/1024 "TOTAL (MBs)",
round((t.totspace-sum(f.bytes))/1024/1024,2) "USED (MBs)",
round(sum(f.bytes)/1024/1024,2) "FREE (MBs)",
round(max(f.bytes)/1024/1024,2) "MAX FREE (MBs)",
round(((t.totspace-sum(f.bytes)) / t.totspace)*100) "% Full"
from dba_free_space f, dba_tablespaces b,
(select tablespace_name,sum(bytes) totspace
from dba_data_files
group by tablespace_name) t
where t.tablespace_name=f.tablespace_name
and t.tablespace_name=b.tablespace_name
group by t.tablespace_name,t.totspace,
b.next_extent,b.EXTENT_MANAGEMENT,b.tablespace_name
order by b.tablespace_name
prompt
prompt
prompt
select max('TOTAL SIZE OF THE DATABASE IS ') "DESCRIPTION",
rpad(round(sum(bytes)/1024/1024/1024,2),5,'0')||' GBs' "SIZE"
from dba_Data_Files
union all
select max('USED SIZE OF THE DATABASE IS '),
rpad(round(sum(bytes)/1024/1024/1024,2),5,'0')||' GBs'
from dba_segments
union all
select max('FREE SPACE AVAILABLE IN THE DATABASE IS '),
rpad(round(sum(bytes)/1024/1024/1024,2),5,'0')||' GBs'
from dba_free_space;
prompt
prompt
E_O_F

(
cat << E_O_F
Space report for $ORACLE_SID Database
E_O_F
echo "\n"
/usr/bin/uuencode $LOG_FILE $LOG_FILE
)|mailx -s "Space Report - $CAP_ORACLE_SID" -c "$Cc_id" $To_id

#####################
### END OF SCRIPT ###
#####################


Wednesday, November 18, 2009

spfile in 9i, 10g and 11g

There is a quite a difference in how your ouput shows up in 9i, 10g and 11g when you do a "show parameter spfile", here is how it shows up if the instance was brought up using an spfile.




Oracle 9i

SQL> sho parameter spfile

NAME TYPE VALUE
-------------------------- ----------- ------------------------------
spfile string ?/dbs/spfile@.ora

Oracle 10g

SQL> sho parameter spfile

NAME TYPE VALUE
-------------------------- ----------- ------------------------------
spfile string /oracle/product/10.2.0/dbs/spfile10G.ora

Oracle 11g

SQL> sho parameter spfile

NAME TYPE VALUE
-------------------------- ----------- ------------------------------
spfile string /oracle/product/11.1.0/dbs/spfile11G.ora




The output in 9i does not show the full ORACLE_HOME location, neither does it display the spfile name while in 10g and above the full ORACLE_HOME location gets displayed along with the spfile name.

Monday, November 9, 2009

ORA-00600 during controlfile recreation

The destructive errors like ORA-00600, ORA-07445 etc show up at unusual times, one such perfect example of getting an ORA-00600 is explained below - it appeared during the execution of CREATE CONTROLFILE script. Before we go any further, here is a quick background of what's being done. A 10.2.0.1 database is to be migrated from one server to another.

As a proactive DBA, which I am not most of the time ;-) - I dumped the control file to the trace and went about creating the scripts to copy the files from the source to destination. All went well until I confronted ORA-600 during the control file recreation.

I had to quickly check the Oracle version which i am currently using, just to make sure there is not a mis-match between the source and destination Oracle binaries. The error pointed me out to a trace file that Oracle usually generates when it needs to provide more information on a particular error.




SQL> CREATE CONTROLFILE REUSE DATABASE "PROD" NORESETLOGS ARCHIVELOG
*
ERROR at line 1:
ORA-01503: CREATE CONTROLFILE failed
ORA-00600: internal error code, arguments: [kccscf_1], [9], [106012], [65535],
[], [], [], []






here is the error entry in alert log






Errors in file /prd/u01/PROD/udump/prod_ora_12326.trc:
ORA-00600: internal error code, arguments: [kccscf_1], [9], [106012], [65535], [], [], [], []
ORA-1503 signalled during: CREATE CONTROLFILE REUSE DATABASE "PROD" NORESETLOGS ARCHIVELOG


UNIX$> more /prd/u01/PROD/udump/prod_ora_12326.trc

ksedmp: internal or fatal error
ORA-00600: internal error code, arguments: [kccscf_1], [9], [106012], [65535], [], [], [], []
Current SQL statement for this session:
CREATE CONTROLFILE REUSE DATABASE "PROD" NORESETLOGS ARCHIVELOG
MAXLOGFILES 255
MAXLOGMEMBERS 5
MAXDATAFILES 12144
MAXINSTANCES 12
MAXLOGHISTORY 106012






Everything looked fine but there is no clue as to what's causing the mighty ORA-600 in this occasion, I gave it a couple of tries myself to troubleshoot before turning over to Mr. Ellison's boys for help!!!. A severity - 1 was raised for this issue and I was pointed out at the value of MAXLOGHISTORY to be equal to 65535 as the maximum limit against the value that I had as 106012.

This looks silly, how come a trace controlfile that was dumped from an SqlPlus session have a value not recommended by Oracle itself. It was later reported by the Oracle technician that its a Bug in 10.2.0.1 which has been fixed in 10.2.0.4. Corrected script is shown below.







CREATE CONTROLFILE REUSE DATABASE "PROD" NORESETLOGS ARCHIVELOG
MAXLOGFILES 255
MAXLOGMEMBERS 5
MAXDATAFILES 12144
MAXINSTANCES 12
MAXLOGHISTORY 65535


Wednesday, November 4, 2009

Datafile naming error

A text editor formatting flaw could really end a life of a DBA in jeopardy, that is what I felt when I realized that one of the tablespaces that I created had a filename with white spaces - such a database gone live into the production is a nightmarish experience. Here is the situation, a tablespace creation script (vi editor) had a filename broken down to the next line and I thought it just came down to the next line after having reached the end of line, but it wasn't. It looked like shown below



CREATE TABLESPACE "USERS_BIG"
LOGGING
DATAFILE '/prd/u01/oradata/prod/users_big01.dbf' SIZE 2500M REUSE,
'/prd/u01/oradata/prod/use
rs_big02.dbf' SIZE 2500M REUSE,
'/prd/u01/oradata/prod/users_big03.dbf' SIZE 5000M REUSE;



This is what it looks like from the inside, of the database and that of the Operating System.



SQL> select file_name from dba_data_files
2 where tablespace_name like '%BIG%';

FILE_NAME
------------------------------------------------------
/prd/u01/oradata/prod/users_big01.dbf
/prd/u01/oradata/prod/use
rs_big02.dbf

/prd/u01/oradata/prod/users_big03.dbf

UNIX:/prd/u01/oradata/prod > ls -ltr
total 184320194
-rw-r----- 1 oracle dba 5242888192 May 22 17:12 users02.dbf
-rw-r----- 1 oracle dba 2621448192 May 22 17:12 use
rs_big02.dbf
-rw-r----- 1 oracle dba 5242888192 May 22 17:12 users01.dbf
-rw-r----- 1 oracle dba 524296192 May 22 17:12 tools02.dbf
-rw-r----- 1 oracle dba 524296192 May 22 17:12 tools01.dbf



Here are some vain efforts to locate the file individually, but nothing worked out.



UNIX:/prd/u01/oradata/prod > ls -ltri
total 184320194
20 -rw-r----- 1 oracle dba 5242888192 May 22 17:12 users02.dbf
19 -rw-r----- 1 oracle dba 5242888192 May 22 17:12 users01.dbf
30 -rw-r----- 1 oracle dba 2621448192 May 22 17:12 use
rs_big02.dbf
18 -rw-r----- 1 oracle dba 524296192 May 22 17:12 tools02.dbf
17 -rw-r----- 1 oracle dba 524296192 May 22 17:12 tools01.dbf

UNIX:/prd/u01/oradata/prod > find ./ -inum "30" -print
./use
rs_big02.dbf
UNIX:/prd/u01/oradata/prod > find ./ -inum "30" -exec ls -ltr {} \;
-rw-r----- 1 oracle dba 2621448192 May 22 17:12 ./use
rs_big02.dbf
UNIX:/prd/u01/oradata/prod > find ./ -inum "30" -exec ls -ltr {} \;|awk '{print $9}'
./use
rs_big02.dbf

UNIX:/prd/u01/oradata/prod > cp "users_big02.dbf" tempos.dbf
cp: cannot access users_big02.dbf



I made a copy of the broken name datafile to a corrected name datafile at the OS level and then renamed it at the database level by including the whitespaces in the source datafile argument of the 'alter database rename file' statement. The copying at the OS level required the entire white spaces to be included in the source file name argument of the 'cp' command, while being enclosed in double quotes (") as shown below.



UNIX:/prd/u01/oradata/prod > cp "use
> rs_big02.dbf" users_big02.dbf

SQL> select file_name from dba_data_files
2 where tablespace_name like '%BIG%';

FILE_NAME
----------------------------------------------------
/prd/u01/oradata/prod/users_big01.dbf
/prd/u01/oradata/prod/use
rs_big02.dbf

/prd/u01/oradata/prod/users_big03.dbf
/prd/u01/oradata/prod/users_big04.dbf


SQL> select tablespace_name,status from dba_tablespaces;

TABLESPACE_NAME STATUS
------------------------------ ---------
SYSTEM ONLINE
UNDO ONLINE
SYSAUX ONLINE
TEMP ONLINE
INDX ONLINE
PERFSTAT ONLINE
TOOLS ONLINE
USERS ONLINE
USERS_BIG ONLINE

9 rows selected.


SQL> alter tablespace users_big offline normal;

Tablespace altered.

SQL> select tablespace_name,status from dba_tablespaces;
TABLESPACE_NAME STATUS
------------------------------ ---------
SYSTEM ONLINE
UNDO ONLINE
SYSAUX ONLINE
TEMP ONLINE
INDX ONLINE
PERFSTAT ONLINE
TOOLS ONLINE
USERS ONLINE
USERS_BIG OFFLINE

9 rows selected.

SQL> !ls -ltr
total 185090258

-rw-r----- 1 oracle dba 5242888192 May 23 04:22 users_big03.dbf
-rw-r----- 1 oracle dba 2621448192 May 23 04:22 users_big01.dbf
-rw-r----- 1 oracle dba 2621448192 May 23 04:22 use
rs_big02.dbf
-rw-r----- 1 oracle dba 10485768192 May 23 04:22 undo.dbf
-rw-r----- 1 oracle dba 209715712 May 23 04:22 redo_PROD_2a.log


SQL> select sum(bytes)/1024/1024,file_name from dba_data_files
2 where tablespace_name like '%USER%'
3 group by file_name order by file_name;

SUM(BYTES)/1024/1024 FILE_NAME
-------------------- -----------------------------------------------
/prd/u01/oradata/prod/use
rs_big02.dbf

5000 /prd/u01/oradata/prod/users01.dbf
5000 /prd/u01/oradata/prod/users02.dbf
5000 /prd/u01/oradata/prod/users03.dbf
5000 /prd/u01/oradata/prod/users04.dbf
/prd/u01/oradata/prod/users_big01.dbf
/prd/u01/oradata/prod/users_big03.dbf
/prd/u01/oradata/prod/users_big04.dbf

8 rows selected.


SQL> alter database rename file '/prd/u01/oradata/prod/use
2 rs_big02.dbf' to '/prd/u01/oradata/prod/users_big02.dbf';

Database altered.


SQL> select sum(bytes)/1024/1024,file_name from dba_data_files
2 where tablespace_name like '%USER%'group by file_name
3 order by file_name;

SUM(BYTES)/1024/1024 FILE_NAME
-------------------- ------------------------------------------------
5000 /prd/u01/oradata/prod/users01.dbf
5000 /prd/u01/oradata/prod/users02.dbf
5000 /prd/u01/oradata/prod/users03.dbf
5000 /prd/u01/oradata/prod/users04.dbf
/prd/u01/oradata/prod/users_big01.dbf
/prd/u01/oradata/prod/users_big02.dbf
/prd/u01/oradata/prod/users_big03.dbf
/prd/u01/oradata/prod/users_big04.dbf

8 rows selected.


SQL> select * from v$recover_file;

FILE# ONLINE ONLINE_ ERROR CHANGE# TIME
---------- ------- ------- ----------------- ---------- ---------
18 OFFLINE OFFLINE OFFLINE NORMAL 0
19 OFFLINE OFFLINE OFFLINE NORMAL 0
20 OFFLINE OFFLINE OFFLINE NORMAL 0
21 OFFLINE OFFLINE OFFLINE NORMAL 0

SQL> alter tablespace USERS_BIG online;

Tablespace altered.


SQL> select * from v$recover_file;

no rows selected


SQL> select sum(bytes)/1024/1024,file_name from dba_data_files
2 where tablespace_name like '%USER%'
3 group by file_name order by file_name;

SUM(BYTES)/1024/1024 FILE_NAME
-------------------- ----------------------------------------------------
5000 /prd/u01/oradata/prod/users01.dbf
5000 /prd/u01/oradata/prod/users02.dbf
5000 /prd/u01/oradata/prod/users03.dbf
5000 /prd/u01/oradata/prod/users04.dbf
2500 /prd/u01/oradata/prod/users_big01.dbf
2500 /prd/u01/oradata/prod/users_big02.dbf
5000 /prd/u01/oradata/prod/users_big03.dbf
5000 /prd/u01/oradata/prod/users_big04.dbf

8 rows selected.



Removing the file at the OS level is a tricky job, the safest is to locate the inode number of the file and use the 'inum' flag of the 'find' command to remove it with the 'exec' flag as shown below



UNIX:/prd/u01/oradata/prod > find ./ -inum "30" -print
./use
rs_big02.dbf
UNIX:/prd/u01/oradata/prod > find ./ -inum "30" -exec ls -ltr {} \;
-rw-r----- 1 oracle dba 2621448192 May 23 04:22 ./use
rs_big02.dbf
UNIX:/prd/u01/oradata/prod > find ./ -inum "30" -exec rm {} \;
UNIX:/prd/u01/oradata/prod >


UNIX:/prd/u01/oradata/prod > ls -tlr
total 184320194
-rw-r----- 1 oracle dba 1048584192 May 23 04:30 sysaux.dbf
-rw-r----- 1 oracle dba 10485768192 May 23 04:42 undo.dbf
-rw-r----- 1 oracle dba 5242888192 May 23 04:45 users_big04.dbf
-rw-r----- 1 oracle dba 5242888192 May 23 04:45 users_big03.dbf
-rw-r----- 1 oracle dba 2621448192 May 23 04:45 users_big02.dbf
-rw-r----- 1 oracle dba 2621448192 May 23 04:45 users_big01.dbf
-rw-r----- 1 oracle dba 9961480192 May 23 04:45 system01.dbf


SQL> select tablespace_name,status from dba_tablespaces;

TABLESPACE_NAME STATUS
------------------------------ ---------
SYSTEM ONLINE
UNDO ONLINE
SYSAUX ONLINE
TEMP ONLINE
INDX ONLINE
PERFSTAT ONLINE
TOOLS ONLINE
USERS ONLINE
USERS_BIG ONLINE

9 rows selected.


Monday, October 12, 2009

Oracle 11gR2 Database Parameters - Reference

Ever since I did the installation of 11g in July this year, I had been longing for a web link of all the database parameters, static and dynamic views of 11g so I could look it for reference just like the 10gR2 and 9iR2, to my surprise - I finally hit it. Master index of parameters and data dictionary description in 11gR2 and a description of v$views in 11gR2 is in here.

Wednesday, October 7, 2009

Metric Collection Error in Grid Control




Target Name=prod.world
Target type=Database Instance
Host=unixhost1
Occurred At=Aug 27, 2009 10:49:40 PM EDT
Message=Metric evaluation error start - Target is in broken state.
Reason - Get dynamic property error,Dynamic Category property error
Severity=Metric Error Start
Acknowledged=No
Notification Rule Name=Database Availability and Critical States
Notification Rule Owner=SYSMAN






If you have OEM Grid Control (OEM-GC) configured on your environment, then the above is sometimes a routine alert page for a database which is a 9.2.0.6.0 being monitored by an OMS of version 10.2.0.5.0. The status for such a database in the Database sub-tab of the Targets tab on OEM-GC shows up some thing like below. The details like database name, server name etc have been shaded out for obvious reasons.
Click on the screen shot for an enlarged view of the picture.




Select the database and hit the configure button on top of the page to configure its settings to change the monitoring account from dbsnmp to the sysdba account. The below screenshots show a step by step procedure.




Change the role to SYSDBA to blank out the Monitor USername and enter 'sys' as the username its password.








Now click the Test Connection to check if the password is accepted and the connection was successful to the database. If not, check if the credentials are correct.





Click Next on top of the page and select "Skip these steps" and click Next for a review and submit it for all the changes to take effect.











The final screen shows the result of successful configuration, click OK to be routed back to the Database Target.




The above solution also fixes the issue of a 9.2.0.6.0 target database core dumping when being associated with an OMS of 10.2.0.5.0

Thursday, October 1, 2009

Users recreation with quotas, privileges and roles

It is quite often in some Oracle shops to refresh databases or a specific schemas of a database using the traditional exp/imp method while retaining the same roles and privileges and other resources is a nerve racking job. Here are some scripts to make life easy for such a DBA to retain the user quotas, privileges and roles (QPR). These scripts generate the sql statements to recreate the QPRs and are named in a sequential order and are to be run in the same sequetial order. Its a known fact that there are misspellings in the script names, which were created when it was a real tizzy situation.


------------------------------
--- 01_useR_recreation.sql ---
------------------------------

set line 150
select 'create user '||username||' identified by values '||
''''||password||''''||' default tablespace '||
DEFAULT_TABLESPACE||' temporary tablespace '||
TEMPORARY_TABLESPACE||' profile '||PROFILE||';' from dba_users 
order by username;

-------------------------------------
--- 02_useR_Quota_recreateion.sql ---
-------------------------------------

set serveroutput on size 1000000 
set line 150
declare
a number;
cursor q is select username,max_bytes,tablespace_name 
from dba_ts_quotas order by username;
begin
for i in q
loop
if i.max_bytes=-1 then
dbms_output.put_line('alter user '||i.username||
' quota unlimited'||' on '||i.tablespace_name||';');
else
dbms_output.put_line('alter user '||i.username||
' quota '||i.max_bytes||' on '||i.tablespace_name||';');
end if;
end loop;
end;
/


---------------------------------------
--- 03_useR_sys_priv_recreation.sql ---
---------------------------------------

set serveroutput on size 1000000
set line 150
declare
cursor user_name is select username from dba_users 
order by 1;
cursor priv (user_nm in varchar2) is select 
distinct(grantee),privilege from dba_sys_privs where 
grantee=user_nm and grantee not in 
('CONNECT','SYSTEM','RESOURCE','SYS','EXP_FULL_DATABASE',
'TSMSYS','RECOVERY_CATALOG_OWNER','SCHEDULER_ADMIN',
'AQ_ADMINISTRATOR_ROLE','DIP','OEM_ADVISOR','DBA',
'IMP_FULL_DATABASE','OEM_MONITOR','DBSNMP','OUTLN') 
order by grantee;
a number;
b varchar2(100);
begin
for i in user_name
loop
for j in priv(i.username)
loop
dbms_output.put_line('grant '||j.privilege||' to '
||i.username||';');
end loop;
end loop;
end;
/


------------------------------------
--- 04_uSer_role_recreateion.sql ---
------------------------------------

set serveroutput on size 1000000
set line 150
declare
cursor user_name is select username from dba_users order 
by 1;
cursor role (user_nm in varchar2) is select distinct 
GRANTEE,granted_role from dba_role_privs where grantee 
not in ('DBSNMP','DIP','OUTLN','SYS','SYSTEM','TSMSYS',
'EXP_FULL_DATABASE','DBA','SELECT_CATALOG_ROLE',
'IMP_FULL_DATABASE','EXECUTE_CATALOG_ROLE',
'LOGSTDBY_ADMINISTRATOR') and grantee=user_nm order by 
grantee;
a number;
b varchar2(100);
begin
for i in user_name
loop
for j in role(i.username)
loop
dbms_output.put_line('grant '||j.granted_role||' to '
||i.username||';');
end loop;
end loop;
end;
/


-----------------------------------------
--- 05_user_tab_privs_recreateion.sql ---
-----------------------------------------

set serveroutput on size 1000000
set line 150
declare
cursor user_name is select username from dba_users 
order by 1;
cursor tab_priv (user_nm in varchar2) is select 
distinct(grantee),owner,table_name,privilege
from dba_tab_privs where grantee not in ('SYSTEM',
'PUBLIC','SELECT_CATALOG_ROLE','GATHER_SYSTEM_STATISTICS',
'EXP_FULL_DATABASE','SYS','EXECUTE_CATALOG_ROLE',
'DELETE_CATALOG_ROLE','LOGSTDBY_ADMINISTRATOR',
'AQ_USER_ROLE','AQ_ADMINISTRATOR_ROLE','HS_ADMIN_ROLE',
'DBA','IMP_FULL_DATABASE','OEM_MONITOR','DBSNMP',
'OUTLN') and grantee=user_nm order by grantee,owner;
a number;
b varchar2(100);
begin
for i in user_name
loop
for j in tab_priv(i.username)
loop
dbms_output.put_line('grant '||j.privilege||' on '||j.owner
||'.'||j.table_name||' to '||i.username||';');
end loop;
end loop;
end;
/



Here is a bonus script to only recreate the passwords of users in a database.


----------------------------------------
--- user_old_password_recreation.sql ---
----------------------------------------

set pages 0
set line 100

select 'alter user '||username||' identified by values '||
''''||password||''''||';' from dba_users order by username;




PS: Please format the lines of code once they have been pasted in your editor as the lines may have been broken down to the next ones while publishing the scripts in a web page

Friday, August 28, 2009

Split utility of Unix

There is a 'split' utility in unix, which allows one to split a sufficiently big file into small chunks of equal sizes. The man pages of split give out more options that could be used based on the need, however a simple example has been shown below in which a text file having 1000 lines has been split into 10 equal chunks of 100 lines each.

The split files have been merged with the help of a 'cat' command in a 'for' loop. Extreme care must be taken when splitting binary/dmp files as splitting succeeds but the merging shows misleading results and the file size of the subjected file before and after the split does not seem to match.

First off, we create a file named 'un_split_file.out', which has 1000 lines - a partial look of it is shown below




UNIX:/prd/u01/acme> export i=0
UNIX:/prd/u01/acme> echo $i
0
UNIX:/prd/u01/acme> while [ "$i" -ne 1000 ]
> do
> echo "This is line $i" >> un_split_file.out
> i=`expr $i \+ 1`
> done &

UNIX:/prd/u01/acme> wc -l split_file.out
1000 split_file.out

UNIX:/prd/u01/acme > head -10 un_split_file.out
This is line 0
This is line 1
This is line 2
This is line 3
This is line 4
This is line 5
This is line 6
This is line 7
This is line 8
This is line 9

UNIX:/prd/u01/acme > tail -10 un_split_file.out
This is line 990
This is line 991
This is line 992
This is line 993
This is line 994
This is line 995
This is line 996
This is line 997
This is line 998
This is line 999

UNIX:/prd/u01/acme > ls -ltr un_split_file.out
-rw-r--r-- 1 oracle dba 16890 Aug 25 05:19 un_split_file.out



Now comes the usage of 'split' command, here 'split' has been passed with 4 arguments



-l 100 -> Line Count, which means after every 100 lines from the beginning of
the files, a new file will be created

-a 2 -> Based on the line count parameter,required number of split files
will be created with a 2 characted substring. The substring by default has
the following trend aa, ab, ac and so on.

Third argument is the name of the file to be split

Fourth argument is the text for naming of the split files


UNIX:/prd/u01/acme> split -l 100 -a 2 un_split_file.out split_file.part_

UNIX:/prd/u01/acme> ls -ltr
total 544
-rw-r--r-- 1 oracle dba 16890 Aug 25 05:19 un_split_file.out
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_aj
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ai
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ah
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ag
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_af
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ae
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ad
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ac
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ab
-rw-r--r-- 1 oracle dba 1590 Aug 25 05:22 split_file.part_aa
UNIX:/prd/u01/acme>





The old file 'un_split_file.out' will be moved to 'un_split_file.out.deleted' so it
does not conflict with the new file that will be created by merging the split files
using the 'cat' command.





UNIX:/prd/u01/acme> mv un_split_file.out un_split_file.out.deleted

UNIX:/prd/u01/acme> for i in `ls split_file.part*`
> do
> cat $i >> un_split_file.out
> done &




The result is the creation of a file named 'un_split_file.out' which has just all
the contents like it did before being split. The split/merge operation does not
remove the source or the original files as seen below.




UNIX:/prd/u01/acme> ls -ltr un_split*
-rw-r--r-- 1 oracle dba 16890 Aug 25 05:19 un_split_file.out.deleted
-rw-r--r-- 1 oracle dba 16890 Aug 25 05:25 un_split_file.out
UNIX:/prd/u01/acme> wc -l un_split_file.out
1000 split_file.out
UNIX:/prd/u01/acme>

UNIX:/prd/u01/acme > ls -ltr
total 578
-rw-r--r-- 1 oracle dba 16890 Aug 25 05:19 un_split_file.out.deleted
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_aj
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ai
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ah
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ag
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_af
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ae
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ad
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ac
-rw-r--r-- 1 oracle dba 1700 Aug 25 05:22 split_file.part_ab
-rw-r--r-- 1 oracle dba 1590 Aug 25 05:22 split_file.part_aa
-rw-r--r-- 1 oracle dba 16890 Aug 25 05:25 un_split_file.out


Thursday, August 6, 2009

Fetching ip addresses of a server names list

server_names_to_ip

This is a script to fetch the ip addresses of server names, the script takes a run time argument of a unique server names list in a file and uses the nslookup command of unix to get the fully qualified server name, its ip address and its alias. The output is stored in the srvr_nmes_2_ip.out file.

The script has to be run on any server on your environment which should be on the same network as do the other servers in the unique server names list. The script is designed for a UNIX environment.




############################################################
#
# Pass a unique server names list as the run time argument
#
# Usage : ksh server_names_2_ip.ksh server_list.parm
#
# Output file : srvr_nmes_2_ip.out
#
############################################################
#
# Name : server_names_2_ip.ksh
#
############################################################
#!/usr/bin/ksh

### pass the server list file as a runtime argument ($1)

server_list=$1
touch srvr_nmes_2_ip.out

for i in $(cat $server_list)
do
F_Q_N=`nslookup $i|grep -i "Name"|awk -F" " '{print $2}'`
F_Q_N_num=`nslookup $i|grep -in "Name"|awk -F":" '{print $1}'`
ip_line_nul=`expr $F_Q_N_num \+ 1`
alias_num=`expr $ip_line_nul \+ 1`
ip_address=`nslookup $i|sed -n "$F_Q_N_num","$alias_num"p|grep "Address"| \
awk -F" " '{print $2}'`
alias_name=`nslookup $i|sed -n "$F_Q_N_num","$alias_num"p|grep "Aliases"| \
awk -F" " '{print $2}'`
echo "$F_Q_N | $ip_address | $alias_name" >> srvr_nmes_2_ip.out
done

###################
## End Of Script ##
###################

#########################################
## Now, view the file srvr_nmes_2_ip.out
## for output
#########################################


Wednesday, July 29, 2009

Error in naming a datafile

At times life as a DBA gets so tiring that you goof up even a simplest task of adding a datafile to a tablespace, I did too (chuckles), I entered a comma(,) instead of a period(.) for the datafile extentsion.



SQL> alter tablespace BLOB_TS add datafile
2 '/prd/u01/oradata/prod/lob08,dbf' size 5000M;




Only after hitting return did I realize that I made a blunder in the datafile name, I had to immediately take the datafile offline to prevent any users from filling it up with data.



SQL> alter database datafile '/prd/u01/oradata/prod/lob08,dbf' offline;

Database altered.

SQL> select status,name from v$datafile where name like '%lob08%';

STATUS NAME
------- ----------------------------------------------------------------
RECOVER /prd/u01/oradata/prod/lob08,dbf



The status above shows that the datafile needs recovery, I ran a 'RECOVER DATAFILE' command to recover the datafile and have its status changed from 'RECOVER' to 'OFFLINE'. In order for this to be successful, the same log sequence should be running in the database if the database is in no-archive mode or it could be a different log sequence if the database is in archive mode but the archive logs be present on disk to be applied if needed.

In my case, it was in archive mode and luckily the same log sequence was running when I ran the 'RECOVER DATAFILE' command



SQL> recover datafile '/prd/u01/oradata/prod/lob08.dbf';
Media recovery complete.

SQL> select status,name from v$datafile where name like '%lob08%';

STATUS NAME
------- ----------------------------------------------------------------
OFFLINE /prd/u01/oradata/prod/lob08,dbf



Now the file has to be copied with the corrected name at the OS level.




SQL> !ls -ltr lob08*
-rw-r----- 1 oracle dba 524296192 Jul 16 10:58 lob08,dbf

SQL> !cp "lob08,dbf" "lob08.dbf"
SQL>

SQL> !ls -ltr lob08*
-rw-r----- 1 oracle dba 524296192 Jul 16 10:58 lob08,dbf
-rw-r----- 1 oracle dba 524296192 Jul 16 11:10 lob08.dbf




The file is then renamed at the database level and should be brought online.



SQL> alter database rename file '/prd/u01/oradata/prod/lob08,dbf' to
2 '/prd/u01/oradata/prod/lob08.dbf';

SQL> alter database datafile '/prd/u01/oradata/prod/lob08.dbf' online;

Database altered.

SQL> select status,name from v$datafile where name like '%lob08%';

STATUS NAME
------- ----------------------------------------------------------------
ONLINE /prd/u01/oradata/prod/lob08.dbf




It is now safe to remove the file with comma(,) in its name at the OS level



SQL> !rm "lob08,dbf"
SQL> !ls -ltr lob08*
-rw-r----- 1 oracle dba 524296192 Jul 16 11:10 lob08.dbf


ORA-06510, ORA-06512 errors during export.

Have you ever received an error like ORA-06510 or ORA-06512 during an export backup of a database ? - The reason behind this is some Oracle shops have a specific database user using which the databases are exported out rather than the traditional admin users like SYS, SYSTEM or an OS authenticated user "/".

The non-admin database user running the export backup does not have an execute privilege on the two packages namely DBMS_EXPORT_EXTENSION and DBMS_DEFER_IMPORT_INTERNAL. A successful execute grant on the two packages to the non-admin user resolves the issue of ORA-06510 and ORA-06512



EXP-00008: ORACLE error 6510 encountered
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at "SYS.DBMS_EXPORT_EXTENSION", line 50
ORA-06512: at "SYS.DBMS_EXPORT_EXTENSION", line 126
ORA-06512: at line 1

SQL> select grantee,owner,table_name,privilege from dba_tab_privs where
2 grantee='EXPORT_USER';

no rows selected

SQL> grant execute on DBMS_EXPORT_EXTENSION to EXPORT_USER;

Grant succeeded.

SQL> grant execute on DBMS_DEFER_IMPORT_INTERNAL to EXPORT_USER;

Grant succeeded.

SQL> select grantee,owner,table_name,privilege from dba_tab_privs where
2 grantee='EXPORT_USER';

GRANTEE OWNER TABLE_NAME PRIVILEGE
---------- ---------- ------------------------------ ----------
EXPORTER SYS DBMS_EXPORT_EXTENSION EXECUTE
EXPORTER SYS DBMS_DEFER_IMPORT_INTERNAL EXECUTE



Wednesday, July 15, 2009

11g Installation

Weeeeeehhho, today I got my hand over the installation of 11gR1(11.1.0.6.0), actually the installation process is no different than its predecessors. The X-windows utility that I used did drag the feet around in the whole installation process as I had to wait patiently (HEIGHTS OF PATIENCE) to get the control over to the buttons/text boxes etc. Although it took quite a while for the installation to complete but in the end it brought a big grin on my face.

RMAN-20011: target database incarnation is not current in recovery catalog

A surprising database backup failure report was delivered to my mailbox, upon checking with the log revealed the below pasted RMAN- errors. This left me wondering as to how come the rman backup would fail for no reason with an error like this, there is something fishy about the situation.



RMAN>
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-06004: ORACLE error from recovery catalog database: RMAN-20011: target
database incarnation is not current in recovery catalog



here are the steps below that were performed to fix the issue of incarnation.



UNIX:~/dba/log > rman target / catalog rman_user/rman_pass@rcat.acme.com

Recovery Manager: Release 10.2.0.1.0 - Production on Mon Jan 26 06:45:20 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

connected to target database: PROD (DBID=2706003900)
connected to recovery catalog database

RMAN> list incarnation of database;


RMAN> exit



as you can see above, no incarnations listed.



UNIX:~/dba/log > . oraenv
ORACLE_SID = [oracle] ? PROD
UNIX:~/dba/log > rman target / nocatalog

Recovery Manager: Release 10.2.0.1.0 - Production on Mon Jan 26 06:46:58 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

connected to target database: PROD (DBID=2706003900)
using target database control file instead of recovery catalog

RMAN> list incarnation of database;


List of Database Incarnations
DB Key Inc Key DB Name DB ID STATUS Reset SCN Reset Time
------- ------- -------- ---------------- --- ---------- ----------
1 1 PROD 2706003900 CURRENT 1 07-FEB-07

RMAN> exit



Now, having logged into the recovery catalog database as the recovery catalog owner and running a couple of queries shown below will give us some background information on the target database DBID and the incarnation id etc.



SQL> select dbinc_key,db_key,db_name from RMAN.dbinc where db_name='PROD';

DBINC_KEY DB_KEY DB_NAME
---------- ---------- --------
875312 875311 PROD


SQL> select DBID, NAME, DBINC_KEY, RESETLOGS_CHANGE#, RESETLOGS_TIME
2 from rc_database_incarnation where dbid=2706003900;

DBID NAME DBINC_KEY RESETLOGS_CHANGE# RESETLOGS
---------- -------- ---------- ----------------- ---------
2706003900 PROD 875312 1 07-FEB-07
2706003900 PROD2 9179422 6.2038E+12 24-MAY-09

SQL> alter session set nls_date_format = 'DD-MON-YYYY HH24:MI:SS' ;

Session altered.

SQL> select DBID, NAME, DBINC_KEY, RESETLOGS_CHANGE#, RESETLOGS_TIME
2 from rc_database_incarnation where dbid=2706003900;

DBID NAME DBINC_KEY RESETLOGS_CHANGE# RESETLOGS_TIME
---------- -------- ---------- ----------------- --------------------
2706003900 PROD 875312 1 07-FEB-2007 15:49:16
2706003900 PROD2 9179422 6.2038E+12 24-MAY-2009 22:25:13



The database PROD with the DBID (2706003900) and DBINC_KEY (875312) has to be reset in the recovery catalog and re-registered for its backups to resume.



UNIX:~/dba/log > rman target / catalog rman_user/rman_pass@rcat.acme.com

Recovery Manager: Release 10.2.0.1.0 - Production on Mon Jan 26 07:00:56 2009

Copyright (c) 1982, 2005, Oracle. All rights reserved.

connected to target database: PROD (DBID=2706003900)
connected to recovery catalog database

RMAN> RESET DATABASE TO INCARNATION 875312;

database reset to incarnation 875312

RMAN> register database;

starting full resync of recovery catalog


full resync complete
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03009: failure of register command on default channel at 05/26/2009 07:40:05
RMAN-20002: target database already registered in recovery catalog

RMAN>
RMAN>



It should have rather been a "resync catalog" than "register database" to suppress the above error.After this, the backup ran to success.



RMAN> list incarnation of database;


List of Database Incarnations
DB Key Inc Key DB Name DB ID STATUS Reset SCN Reset Time
------- ------- -------- ---------------- --- ---------- ----------
875311 875312 PROD 2706003900 CURRENT 1 07-FEB-07
875311 9179422 PROD2 2706003900 ORPHAN 6203845546338 24-MAY-09

RMAN> exit


Recovery Manager complete.


Monday, July 13, 2009

DBMS_METADATA.GET_DDL

Oracle introduced the usage of DBMS_METADSATA package's GET_DDL function to retrieve the DDL of a particular object type from 9i onwards. It takes two/three arguments depending on the type of object you want to retrieve the DDL for.



GENERAL USAGE

set long 300000 pages 0 lines 140

SELECT DBMS_METADATA.GET_DDL('OBJECT_TYPE','OBJECT_NAME','OWNER') FROM DUAL;



The 'OWNER' argument is sometimes optional if you are connected as the same user who owns the object you are trying to retreive the DDL for. Pasted below are the statements to generate the DDL for most of the object types.



select dbms_metadata.get_ddl('CLUSTER','C_MLOG#','SYS') from dual;

select dbms_metadata.get_ddl('CONTEXT','LT_CTX') from dual;

select dbms_metadata.get_ddl('DB_LINK','PROD.WORLD','ADAM') from dual;

select dbms_metadata.get_ddl('DB_LINK','TEST.WORLD','PUBLIC') from dual;

select dbms_metadata.get_ddl('FUNCTION','TO_DATE_FUNC','SCOTT') from dual;

select dbms_metadata.get_ddl('INDEX','REPCAT$_REPCOLUMN_PK','SYSTEM') from dual;

select dbms_metadata.get_ddl('JAVA_SOURCE','java_util','ADAM') from dual

select dbms_metadata.get_ddl('JAVA_SOURCE','/6c363944_Dumper','SYS') from dual

select dbms_metadata.get_ddl('LIBRARY','UTL_SMT_LIB','SYS') from dual;

select dbms_metadata.get_ddl('MATERIALIZED_VIEW','BS_TAB_MV','SYS') from dual;

select dbms_metadata.get_ddl('MATERIALIZED_VIEW_LOG','MLOG$_BS_TABLE','SYS') from dual;

select dbms_metadata.get_ddl('OPERATOR','OLAP_EXPRESSION') from dual;

select dbms_metadata.get_ddl('OPERATOR','OLAP_EXPRESSION','SYS') from dual;

select dbms_metadata.get_ddl('PACKAGE','XMLPARSER') from dual;

select dbms_metadata.get_ddl('PACKAGE','XMLPARSER','SYS') from dual;

select dbms_metadata.get_ddl('PACKAGE_BODY','STATSPACK','PERFSTAT') from dual;

select dbms_metadata.get_ddl('PROCEDURE','ORA$_SYS_REP_AUTH','SYSTEM') from dual;

select dbms_metadata.get_ddl('SEQUENCE','STATS$SNAPSHOT_ID','PERFSTAT') from dual;

select dbms_metadata.get_ddl('SYNONYM','/2fddc42_paintARGB_PRE_ONTO_S5','PUBLIC') from dual;

select dbms_metadata.get_ddl('TABLE','SQLEXPERT_PLAN1','SYSTEM') from dual;

select dbms_metadata.get_ddl('TABLESPACE','USERS') from dual;

select dbms_metadata.get_ddl('TRIGGER','DEF$_PROPAGATOR_TRIG','SYSTEM') from dual;

select dbms_metadata.get_ddl('TYPE','XMLSEQ_IMP_T','SYS') from dual;

select dbms_metadata.get_ddl('TYPE_BODY','ORACLE_LOADER','SYS') from dual;

select dbms_metadata.get_ddl('VIEW','DBA_PROPAGATION','SYS') from dual;

select dbms_metadata.get_ddl('VIEW','DBA_PROPAGATION') from dual;

select dbms_metadata.get_ddl('PACKAGE','DBMS_METADATA','SYS') from dual;

Friday, June 26, 2009

Database Creation errors

Here is a quick post on the number and type of errors that get reported during the execution of catalog.sql and catproc.sql script at database creation.

The execution of catalog.sql results in just 5 errors which has been tested successully in both 9i and 10g. The errors are listed below, any other error besides what is given below is sure a matter of concern for the DBA which needs to be sorted out appropriately based on the error.



UNIX$> grep "^ORA-" catalog.log
ORA-01432: public synonym to be dropped does not exist
ORA-01432: public synonym to be dropped does not exist
ORA-00942: table or view does not exist
ORA-01921: role name 'EXP_FULL_DATABASE' conflicts with another user or role
ORA-01921: role name 'IMP_FULL_DATABASE' conflicts with another user or role



Now, the catproc.sql reports quite a lot of errors, all of which can be ignored. The number of errors that get reported during the execution of catproc.sql vary from platform to platform and from release to release. The number of errors generated in a 10.2.0.4 - 64 bit database on a 64-bit sparc Solaris machine are 435.



UNIX$> grep -c "^ORA-" catproc.log
435



Below is a list of all the errors that formed the number 435,



ORA-04043

ORA-00942

ORA-02289

ORA-01434

ORA-01432

ORA-29807


UNIX$> grep "^ORA-" catproc.log|grep -v "ORA-04043"|grep -v "ORA-00942" |\
> grep -v "ORA-02289"|grep -v "ORA-01434"|grep -v "ORA-01432"|grep -v "ORA-29807"




As it is evident that bypassing the above list of 6 types of ORA- errors does not show up any more errors in the catproc.log, so the count of ORA- errors does not really matter but the actual ORA- error does.

Monday, May 25, 2009

Date Format

The date columns in SQL* Plus are returned in the format 'DD-MON-YY', in order to obtain the time along with the date - one uses to_char() function with the date datatype column and the date format as arguments to display the date along with timestamp in what ever format one desires.

Say a query against a table which has only date columns then it is highly frustrating to use the to_char function on every data datatype column to change the format to include the timestamp. This is where the NLS_DATE_FORMAT parameter comes into picture. Set the NLS_DATE_FORMAT to what ever format the date has to be displayed, all the date datatypes columns in a query return the output in the same format specified with NLS_DATE_FORMAT. Look at the examples below.


SQL> select last_date,next_date from dba_jobs;

LAST_DATE NEXT_DATE
--------- ---------
24-MAY-09 25-MAY-09
25-MAY-09 25-MAY-09
09-FEB-09 01-JAN-00
01-MAR-09 01-JAN-00
24-MAY-09 25-MAY-09
25-MAY-09 25-MAY-09
25-MAY-09 26-MAY-09
24-MAY-09 25-MAY-09
24-MAY-09 25-MAY-09
25-MAY-09 26-MAY-09
25-MAY-09 26-MAY-09
25-MAY-09 26-MAY-09
24-MAY-09 25-MAY-09
24-MAY-09 25-MAY-09
24-MAY-09 25-MAY-09
24-MAY-09 25-MAY-09

16 rows selected.

SQL> alter session set NLS_DATE_FORMAT = 'mm-dd-yyyy HH24:mi:ss';

Session altered.

SQL> select last_date,next_date from dba_jobs;

LAST_DATE NEXT_DATE
------------------- -------------------
05-24-2009 09:56:49 05-25-2009 08:56:49
05-25-2009 05:28:03 05-25-2009 05:34:03
02-09-2009 16:48:24 01-01-4000 00:00:00
03-01-2009 23:19:11 01-01-4000 00:00:00
05-24-2009 16:18:10 05-25-2009 15:18:10
05-25-2009 00:02:09 05-25-2009 23:00:00
05-25-2009 01:02:12 05-26-2009 00:00:00
05-24-2009 18:28:18 05-25-2009 17:28:18
05-24-2009 21:03:09 05-25-2009 09:03:09
05-25-2009 00:00:03 05-26-2009 00:00:00
05-25-2009 00:00:13 05-26-2009 00:00:04
05-25-2009 00:00:14 05-26-2009 00:00:04
05-24-2009 18:28:13 05-25-2009 17:28:13
05-24-2009 16:15:01 05-25-2009 15:15:01
05-24-2009 16:15:00 05-25-2009 15:15:00
05-24-2009 16:14:59 05-25-2009 15:14:59

16 rows selected.

Tuesday, May 12, 2009

STARTUP arguments

This post enlightens the usage of options with the STARTUP command of an Oracle database. When using the PFILE argument of the STARTUP command, the init.ora parameter does not necessarily be in $ORACLE_HOME/dbs directory - but can be located anywhere else while the actual path along with the file name has to be mentioned as a value for the PFILE argument. The SPFILE.ORA can be located in only one place, $ORACLE_HOME/dbs. Irrespective of wherever the PFILE is located a "CREATE SPFILE FROM PFILE" will create the SPFILE only in $ORACLE_HOME/dbs directory.


SQL> sho parameter spfile

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
spfile string C:\ORACLE\10.2.0\DATABASE\SPFI
LEORCL10.ORA
SQL> startup force
ORACLE instance started.

Total System Global Area 264241152 bytes
Fixed Size 1248428 bytes
Variable Size 100664148 bytes
Database Buffers 155189248 bytes
Redo Buffers 7139328 bytes
Database mounted.
Database opened.

SQL>
SQL> startup spfile="C:\Documents and Settings\oracle_and_unix\Desktop\SPFILEORCL10.ORA"
SP2-0714: invalid combination of STARTUP options

SQL> startup force spfile="C:\Documents and Settings\oracle_and_unix\Desktop\SPFILEORCL10.ORA"
SP2-0714: invalid combination of STARTUP options

SQL> startup pfile="C:\Documents and Settings\oracle_and_unix\Desktop\initorcl10.ora"
ORA-01081: cannot start already-running ORACLE - shut it down first

SQL> startup force pfile="C:\Documents and Settings\oracle_and_unix\Desktop\initorcl10.ora"
ORACLE instance started.

Total System Global Area 264241152 bytes
Fixed Size 1248428 bytes
Variable Size 104858452 bytes
Database Buffers 150994944 bytes
Redo Buffers 7139328 bytes
Database mounted.
Database opened.

SQL> sho parameter pfile

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
spfile string
SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

SQL> startup pfile="C:\Documents and Settings\oracle_and_unix\Desktop\initorcl10.ora"
ORACLE instance started.

Total System Global Area 264241152 bytes
Fixed Size 1248428 bytes
Variable Size 104858452 bytes
Database Buffers 150994944 bytes
Redo Buffers 7139328 bytes
Database mounted.
Database opened.
SQL> sho parameter spfile

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
spfile string

SQL> create spfile from pfile;

File created.

SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.

Total System Global Area 264241152 bytes
Fixed Size 1248428 bytes
Variable Size 100664148 bytes
Database Buffers 155189248 bytes
Redo Buffers 7139328 bytes
Database mounted.
Database opened.
SQL> sho parameter spfile

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
spfile string C:\ORACLE\10.2.0\DATABASE\SPFI
LEORCL10.ORA
SQL>

Wednesday, April 8, 2009

WRAP utility of Oracle

It is really fun to hide your code from others, even if the scripts are out there for everyone to see - one makes sure that the passers by not able to comprehend what a particular script does. The easiest way to do that would be to remove all the comments that you would have made in the code for your own understanding about each and every routine of a script. But an expert programmer can actually say what the script is doing in no time.

Oracle comes with its very own utility of encrypting a procedure/function or a package for that matter. This encryption is achieved using the wrap utility from $ORACLE_HOME/bin. Wrap takes two arguments 'iname' and 'oname'.

iname - name of the input file name
oname - name of the output file name.

Although 'oname' is optional, however it is a good practice to include 'oname' in the command to give a user defined output file name. If 'oname' is skipped, then the wrap utility creates the output file in the same name as that of the 'iname but with an extension of 'plb'.

Let us understand this more clearly with an example. Here is a procedure code in a file test_proc.txt which will be wrapped to obfuscate the code.



-------------------
--- test_proc.txt -
-------------------

create or replace procedure p1 as
a number;
b varchar2(20);
begin
select username into b from dba_users where username='SYSTEM';
dbms_output.put_line(chr(0));
dbms_output.put_line(b);
end;
/



The above script test_proc.txt will be wrapped without mentioning an output file, results in the creation of test_proc.plb file as shown below.




C:\Documents and Settings\oracle_and_unix\Desktop>wrap iname=test_proc.txt

PL/SQL Wrapper: Release 10.2.0.1.0- Production on Fri Mar 27 15:49:38 2009

Copyright (c) 1993, 2004, Oracle. All rights reserved.

Processing test_proc.txt to test_proc.plb

C:\Documents and Settings\oracle_and_unix\Desktop>




Below is example which uses the oname parameter of the wrap utility.



C:\Documents and Settings\oracle_and_unix\Desktop>wrap iname=test_proc.txt oname=proc.sql

PL/SQL Wrapper: Release 10.2.0.1.0- Production on Fri Mar 27 15:53:53 2009

Copyright (c) 1993, 2004, Oracle. All rights reserved.

Processing test_proc.txt to proc.sql

C:\Documents and Settings\oracle_and_unix\Desktop>




The script/file generated as the output of the wrap command could be used to run in the sql prompt which actually does the job of the original sql script. The contents of the wrapped file are only readable by the Oracle server which leaves the user only wonder about the junk found in the wrapped script.


Note : The contents of the wrapped script cannot be changed to make changes to the code. In order to do that, the original script has to be editted with the changes and generate a new wrapped script.


The contents of the test_proc.plb script is shown below to give you a glance of how the wrapped script looks like.



create or replace procedure p1 wrapped
a000000
b2
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
7
ac ce
izB2dE4cerXXikkhm/Ipr/ZX/L4wgzJHLcvhqC82afa84JjW1G6x05lvK6itj8KZq9U/r7Vk
2xUl4Bj6E0evPV59WaW8qbZpy/JyWn6UFWot0Ep47TvJn0WwUUafm7JFLx+cvQnelC9IcYI2
9YaZ4XJaTpt4RdGb8WBCLcVwp8wS2iPacl8AlCUiwofwOoxXN/JLsCjkc1a0

/




Most of the scripts/packaged scripts that are called in the catproc.sql script are already wrapped by oracle, so no expert DBA/Developer can meddle with them....I wish if there is any such wrapping at the UNIX operating system level to encrypt all
the shell scripts....(chuckles)

Thursday, March 19, 2009

Shell Script - eliminate duplicate patterns in a list

Here is a shell script to eliminate duplicate patterns in a list of patterns.


#################################################
# Let the name of the file containing the list
# of patterns be named 'tst.parm'
#
# Name : uniq_patern.ksh
#################################################

#!/usr/bin/ksh

fil=tst.parm
touch new_list
for i in $(cat $fil)
do
grep -vi "$i" $fil > x
var=`echo $i`
if [ `/usr/xpg4/bin/grep -iq "$var" new_list; echo $?` -ne 0 ]
then
echo "$i" >> new_list
else
##echo "entry already exist" > /dev/null
echo "entry already exist"
fi
mv x fil
done

#########
# E N D #
#########

#################################################
# Now view the file 'new_list' for a list of
# patterns that are not duplicated
#################################################



Here is the parameter file 'tst.parm' that was passed to the script, the tst.parm file has a list of duplicated patterns



unix$> cat tst.parm
one
ONE
two
three
ONE
two
TWO
one
THREE
one



Once after executing the script uniq_patern.ksh, the result is stored in 'new_list' file.


unix$> cat new_list
one
two
three

Wednesday, March 11, 2009

Shared Memory and Semaphores

This MetaLink document gives an elaborate insight of how Oracle acquires shared memory segments and semaphores for a particular instance during startup. Doc id : 15566.1

Tuesday, March 3, 2009

ps and pargs for command line arguments

Here is a quick note on how to find the arguments (command line parameters) passed to a script or a running process. A simple "ps -ef|grep process_name" gives the details of a given process along with the arguments passed to it. If the arguments are more than what the system's output could show up then it is really hard to find the arguments that have gone into the execution of a process/script.

ps command has various flags in itelf, when used appropriately will give you exactly what you are looking for.pargs is another command to see the arguments that have been passed to a process or a script. The working of the two commands have been shown below, visiting the man pages of both the binaries will give access to a lot of other options which when used will give out astounding results.

The below examples display all the command line arguments, but if there is a script/process executing with a very big list of command line arguments - these commands will be helpful.









The below slide shows that pargs has no effect on a zombie process, in this case it is the "grep rman" process.





In the below slide it shows the output of running the 'ps' command on the process id 1332, which is a parent process for a couple of processes(see in very first slide). This has the arguments as /usr/sbin/cron, which is a cron process and is only usable by "root" user.



But the pargs command on 1132 has not effect, infact there is a "permission denied" message output since it is owned by root.



In the above slide, there are two new arguments - ppid and user.

ppid - parent process id
user - user who owns the process

Now let us play a little with the ppid argument of ps command. Following slide shows the output for 29029 process id, this process id is a parent process for 29037 process and child process for 1132.



We already know that 1132 is "/usr/sbin/cron" process owned by root, when searching for more details on 1132 process it is found that 1132 has a ppid of 1 and a state of S (process is in sleep mode, waiting for an event to complete). Here the "s" flag of ps gives the state of a process.



Let us now search for the process with pid 1 and then a search with the ppid of 1. The slides below have a truncated output, since a number '1' or '0' could be found in - if not all the processes but most of the processes.



Here the pid 1 has a parent process of 0, which has a state of T that means Process is stopped, either by a job control signal or because it is being traced.

Thursday, February 12, 2009

startup / shutdown order

This post will explain the order of startup/shutdown of listeners and databases.
A listener is the only process which lets a client connection know that if a
database is up and running fine and that it is ready to accept incoming connections.
As long as the database is running fine, it shows active in the LSNRCTL STATUS LISTENER output.

Let me demonstrate some of the points to remember when bringing up the databases and
listeners, the order in which they are to be brought up, how to interpret the
LSNRCTL STATUS LISTENER output and some good practices.

The below slide shows a listener named LISTENER having static handlers to all the
databases it listens for, the output shows a handler of 'UNKNOWN' status for each of
the database services chicago, sudo, boston and orcl10. This means that the
databases are neither registered with the instance nor are they up.



The status of CHICAGO has been highlighted since this is the database which will be
considered in the experimentation. As discussed above, CHICAGO is not up. Let for
the time being shut the LISTENER down and bring up the database CHICAGO and then
bring the listener up, the idea is to defer the process of instance registration by
the pmon process (ora_pmon_chicago) with the listener.

The slides below show that CHICAGO database is up and running fine, the LISTENER is
running ok but the database CHICAGO has not been registered with the LISTENER which
is evident with just 1 handler of UNKNOWN status.







Now, the database is manually registered with the LISTENER and the results look like
shown below.





The slide above shows that CHICAGO database now has two handlers, each with UNKNOWN
and READY status. Now let us do the same process of bouncing the LISTENER and
database, but in proper order this time.







The is the reason why Oracle Corp. always suggests that the LISTENERS be brought up
before the databases come online, so when the instance gets started all the
background processes which get initialized start doing their job right from the
first moment.This initial processing also lets the pmon process to register the
database service with the listener.

The best practice of starting up/shutting down the databases and listeners is



Although, this is not the case from Oracle 8i and hence forth since Oracle server
offers dynamic instance registration from 9i onwards. If even we do not bring the
databases and listeners in proper order, the pmon eventually performs its job of
registration - sometimes a delayed registration.

How to use SET AUTOTRACE

Let us see the different forms of using SET AUTOTRACE commands that are offered by
Oracle. First off, what is the syntax of using SET AUTOTRACE, I knew it starts with
SET AUTOTRACE - but what after that. so I did a SET AUTOTRACE and hit enter and I
was surprised to see that Oracle helps in finding the exact syntax of using SET AUTOTRACE.



Later I realized that any character or number followed by SET AUTOTRACE, gives the
above mentioned help menu.



Let us see how each and every option works when used.




Just SET AUTOTRACE ON, returns all the rows of the query followed by the execution
plan and statistics of the query run. Now, SET AUTOTRACE TRACE which is synonymous
to SET AUTOTRACE TRACEONLY does not return the rows of the query but returns the
count of rows (like it always does at the end of every SELECT query) along with the
execution plan and the statistics of the query.



SET AUTOTRACE TRACE works differently if it just takes explain - returns only the
explain plan of the query skipping the statistics.



Now I would like the statistics but no explain plan - run SET AUTOTRACE TRACE STATISTICS



The keywords EXP[LAIN] or STAT[ISTICS] do not work without either ON or TRACE[ONLY]
keyword, as shown below



Just a SET AUTOTRACE ON - returns the rows of the SELECT query, displays the explain
plan along with the statistics. Here are some more situations - playing around with
the keywords in one order or the other.

SET AUTOTRACE ON EXPLAIN - Returns the rows and explain plan, skipping the statistics



SET AUTOTRACE ON STAT - Returns the rows and statistics thereby skipping the execution plan.



However, just the TRACE[ONLY] keyword does not work with SET AUTOTRACE ON, neither
does the EXP[LAIN] or STAT[ISTICS] keywords.



Note : after every run of the query in different situations, the following statements were run to clear the shared pool and buffer cache.




This implies that SET AUTOTRACE ON is really of no use for us, DBAs, since it
returns the result set of the query before it shows up the explain plan and the
statistics of the query - If the result set is of say 10 million records then one
has to wait for all the records to come up before (s)he gets a chance to look at the
explain plan and statistics. It is suggested to use SET AUTOTRACE TRACE as it gives
us the information of number of rows returned, explain plan and statistics.

Monday, January 5, 2009

SCP Automation.

Today's world is fully automated, so are the responsibilities of a DBA. Starting from checking alert logs for ORA- errors to checking if a listener/database is active. Whenever there is something that need to be done is not automated, a DBA starts muttering about the job. One such automation requirement is an SCP transfer of files from one server to another.

Most of the environments now prefer ssh connection to the unix hosts over conventional telnet, and one drawback of ssh connection to a host is it does not allow for FTP access. The ultimate solution for this would be to SCP the files. But SCP requires a user be authenticated before the copy could actually start.

Before we move on any further, lets see how SCP works. Here is a scenario to make things understandable. A DBA wants to transfer a file from one host(source) to another host(destination), the command goes like this

source$> scp oracle@destination_ip_or_hostname:$HOME/.

Once the enter key is hit, password for the destination oracle user is prompted - since this is a secure copy. If the number of files that are to be copied are just a few, say less than 5, one does not feel it mundane to key in the password. However if the files to be transferred are more in number say 10, 20 or lets keep it to 50 (big enough), one has to bear the brunt of keying in the password for as many number of files to be transferred.

This authentication mechanism could be skipped if the password key of the source is appended to a file in destination. Let us see how this works. There is a .ssh directory under $HOME directory under every user of a host in an ssh environment, which is where all the authentication of a remote host takes place. Now navigate to .ssh

host1@/export/oracle/home/$>cd .ssh
host1@/export/oracle/home/.ssh$>

Enter the below command to generate a public/private rsa key pair and accept defaults for name of the file to save the password key, also Enter no passphrase, hit enter when prompted for a passphrase.




If the file(s) already exist, the command execution would like shown below.




The above command generates two files, id_rsa and id_rsa.pub. id_rsa.pub is the public key of this host, which has to be transmitted to the destination where you intend to secure copy the files. Offcourse the file id_rsa.pub has to be transmitted by entering the password for the remote host.



Now the contents of id_rsa.pub file has to be appended to the authorized_keys file in the destination host under the directory $HOME/.ssh/



We are now good to go for transfering files over SCP without being prompted for a password. This is really helpful in transfering files using a shell script where a list of SCP syntaxes of files to be transferred are specified in a script.

Note: The above procedure was only tested and implemented on Sun Solaris and HP -UX, for the rest of the flavours of UNIX - it is highly recommended to go through the OS manual or implement on a test environment before moving to production.