Thursday, December 8, 2022

Prune GI/DB oui-patch.xml inventory files of old patches to speed up patching.

take these actions to subvert unpublished oracle bug 

Bug 33425636 – OPATCHAUTO VER 27 BINARIES APPLY TAKES LONG TIME

PROBLEM STATEMENT: 

  • The more patches you have historically applied, the longer the binary patching takes
  • The more cluster nodes you have, the longer it takes
  • The more databases you run on each cluster node, the longer it takes
  • The more PDBs you have, the longer it takes

readOuiPatch.py and pruneOuiPatch.py both written in python 2.7.5

- read inventory file

#!/bin/python

#
# readOuiPatch.py
#
import xml.etree.ElementTree as ET
import sys
import logging
import socket
import os
import os.path
if os.getenv('ORACLE_HOME'):
    l_orasid = os.getenv('ORACLE_SID')
    l_orahome = os.getenv('ORACLE_HOME')
else:
    print("environment not set.")
    sys.exit(1)
l_orasid = os.getenv('ORACLE_SID')
l_orahome = os.getenv('ORACLE_HOME')
l_fname="oui-patch.xml"
l_fname_path=l_orahome + "/inventory/ContentsXML/" + l_fname
if not os.path.exists(l_fname_path):
    print("")
    print("Inventory File:" + l_fname_path + ' does not exists or is not readable.')
    sys.exit(1)
else:
    print("")
    print("Inventory File:" + l_fname_path)
    print("")
tree = ET.parse(l_fname_path)
root = tree.getroot()
for oneoff in root.findall('ONEOFF'):
    desc = oneoff.find('DESC').text
    refid = oneoff.get('REF_ID')
    print(refid, desc)

-prune inventory file
# note: pass list of oneoff patch ids into this script.
#!/bin/python
#
# pruneOuiPatch.py
#
import xml.etree.ElementTree as ET
import sys
import logging
import socket
import os.path
import shutil
import datetime as dttm
def remove_patch(patch_id):
    l_out=''
    try:
        xmltree = ET.parse(l_fname_path)
        root = xmltree.getroot()
        for idx, oneoff in enumerate(root.findall('ONEOFF')):
            refid = oneoff.get('REF_ID')
            if refid==patch_id:
                root.remove(root[idx])
                xmltree.write(l_fname_path, encoding='UTF-8', xml_declaration=True)
                l_out=str(patch_id) + ':Removed'
                break
            else:
                l_out=str(patch_id) +':NotFound'
    except:
        l_out=str(patch_id) +':SomethingElse'
    return l_out
l_example= "    Example:"
l_example_msg = "    oracle> " + sys.argv[0] + " 1234,5678"
l_patch_list = []
l_fname = "oui-patch.xml"
# read patch list into py list.
if(len(sys.argv) == 2):
    l_patch_list=sys.argv[1].split(',')
elif(len(sys.argv) >= 3):
    print("")
    logging.critical("Too many variables provided.")
    print("")
    print(l_example)
    print(l_example_msg)
    sys.exit(1)
else:
    print("")
    logging.critical("No patchlist provided.")
    print("")
    print(l_example)
    print(l_example_msg)
    sys.exit(1)
if os.getenv('ORACLE_HOME'):
    l_orasid = os.getenv('ORACLE_SID')
    l_orahome = os.getenv('ORACLE_HOME')
else:
    print("")
    logging.critical("environment not set.")
    print("")
    sys.exit(1)
l_basedir = l_orahome + "/inventory/ContentsXML"
l_dttm = '.' + dttm.datetime.now().strftime('%Y%m%d_%H%M%S')
l_fname_path = l_basedir + "/" + l_fname
l_backup_fname_path = l_fname_path + l_dttm
if not os.path.exists(l_fname_path):
    print(l_fname_full + ' does not exists or is not readable.')
    sys.exit(1)
# backup existing oui-patch.xml file
shutil.copy(l_fname_path,l_backup_fname_path)
for patch in l_patch_list:
    print(remove_patch(str(patch)))
print("")
print("Inventory Base: " + l_basedir)
print("Inventory File: " + l_fname)
print("Backup: " + l_fname + l_dttm)



######
# sample execution

#######
oracle> echo $ORACLE_SID
CSBD818


(/opt/lbin)
oracle> echo $ORACLE_HOME
/opt/dev/oracle/product/db/19


(/opt/lbin)
oracle> ./readOuiPatch.py
Inventory File:/opt/dev/oracle/product/db/19/inventory/ContentsXML/oui-patch.xml
('29517242', 'Database Release Update : 19.3.0.0.190416 (29517242)')
('29585399', 'OCW RELEASE UPDATE 19.3.0.0.0 (29585399)')
('30894985', 'OCW RELEASE UPDATE 19.7.0.0.0 (30894985)')
('30869156', 'Database Release Update : 19.7.0.0.200414 (30869156)')
('32218454', 'Database Release Update : 19.10.0.0.210119 (32218454)')
('32222571', 'OCW Interim patch for 32222571')
('32545013', 'Database Release Update : 19.11.0.0.210420 (32545013)')
('33806152', 'Database Release Update : 19.15.0.0.220419 (33806152)')


oracle> ./pruneOuiPatch.py 29517242,29585399
29517242:Removed
29585399:Removed
Inventory Base: /opt/dev/oracle/product/db/19/inventory/ContentsXML
Inventory File: oui-patch.xml
Backup: oui-patch.xml.20221208_080047


oracle> ./readOuiPatch.py
Inventory File:/opt/dev/oracle/product/db/19/inventory/ContentsXML/oui-patch.xml
('30894985', 'OCW RELEASE UPDATE 19.7.0.0.0 (30894985)')
('30869156', 'Database Release Update : 19.7.0.0.200414 (30869156)')
('32218454', 'Database Release Update : 19.10.0.0.210119 (32218454)')
('32222571', 'OCW Interim patch for 32222571')
('32545013', 'Database Release Update : 19.11.0.0.210420 (32545013)')
('33806152', 'Database Release Update : 19.15.0.0.220419 (33806152)')
# patches removed from oui-patch.xml inventory. 
('29517242', 'Database Release Update : 19.3.0.0.190416 (29517242)')
('29585399', 'OCW RELEASE UPDATE 19.3.0.0.0 (29585399)')

credit and much thanks to Mike Dietrich for adding context and clarity on this bug. 
https://mikedietrichde.com/2022/05/10/binary-patching-is-slow-because-of-the-inventory/

good luck and happy patching. 

-huck

Tuesday, April 5, 2022

PGA Historical Growth PDB

 sql> show pdbs

retrieve pdb con_id

set linesize 200
col begin_time for a30
col end_time for a30
select snap_id, CON_DBID, begin_time, end_time, pga_bytes/1024/1024/1024
from DBA_HIST_RSRC_PDB_METRIC
where con_id =4
order by 1;



Monday, January 24, 2022

AWR/ADDM Snapshot settings: CDB/PDB

get current:

SELECT con_id, extract(day from snap_interval) *24*60+extract(hour from snap_interval) *60+extract(minute from snap_interval) snapshot_Interval,

extract(day from retention) *24*60+extract(hour from retention) *60+extract(minute from retention) retention_Interval

FROM dba_hist_wr_control;


19c new feature, enable addm in pdb.

ALTER SYSTEM SET AWR_PDB_AUTOFLUSH_ENABLED=TRUE scope=both sid='*';


EXEC dbms_workload_repository.modify_snapshot_settings(interval=>60);



references:
19c New Feature Support ADDM Analysis for PDBs (Doc ID 2644341.1)
https://support.oracle.com/epmos/faces/DocumentDisplay?_afrLoop=124474630246449&id=2644341.1&_afrWindowMode=0&_adf.ctrl-state=8xemq01j2_160


Wednesday, January 5, 2022

TNSPING sqlnet Timeout option for net address not reachable.

sqlnet.ora timeout for tnsping of offline host/vip address, this would normally hang your tnsping for 3 minutes, if you have 1500+ entries in a global tns file, with many of them dead of offline for maintenance, that adds up quickly. 


###########################

# tnsping host/vip timeout option 

TCP.CONNECT_TIMEOUT=1

###########################


Oracle Tablespace Usage Script

shows allocated and used space and percentages.

# tbs_usage.sql

def aps_prog    = 'tf.sql'

def aps_title   = 'Database Freespace Summary'

set linesize 200

col tsname  format         a24 heading 'Tablespace'

col nfrags  format 999,990     justify c heading 'Free|Frags'

col mxfrag  format  99,990 justify c heading 'Largest|Free Frag'

col totsiz  format 99,999,990 justify c heading 'Total|Mbytes'

col filsiz  format 99,999,990 justify c heading 'File|Mbytes'

col avasiz  format 99,999,990 justify c heading 'Available|Mbytes'

col pctusd  format     990.99  justify c heading 'Percent|Used'

set pages 200

select

  total.tablespace_name                       tsname,

  count(free.bytes)                           nfrags,

  nvl(max(free.bytes)/1048576,0)              mxfrag,

  total.bytes/1048576                         totsiz,

  total.file_bytes/1048576                    filsiz,

  nvl(tot_free.free_bytes,0)/1048576              avasiz,

  --nvl(used.bytes,0)/total.bytes*100  pctusd

 (total.file_bytes-nvl(tot_free.free_bytes,0))/total.bytes*100  pctusd

from

  (select

tablespace_name,

sum(bytes) file_bytes,

SUM(CASE WHEN maxbytes > bytes THEN maxbytes ELSE bytes END)       bytes

from

dba_data_files

where tablespace_name not like 'UNDO%'

group by

tablespace_name)

  total,

  (select

tablespace_name,

nvl(sum(bytes),0) free_bytes

from

dba_free_space

group by

tablespace_name) tot_free,

dba_free_space  free

where

  total.tablespace_name = free.tablespace_name(+)

and   total.tablespace_name = tot_free.tablespace_name(+)

group by

  total.tablespace_name,

  total.bytes,

  free_bytes,

  file_bytes

order by 7

/

select

  total.tablespace_name                       tsname,

  count(free.bytes)                           nfrags,

  nvl(max(free.bytes)/1048576,0)              mxfrag,

  total.bytes/1048576                         totsiz,

  total.file_bytes/1048576                    filsiz,

  nvl(tot_free.free_bytes,0)/1048576              avasiz,

  --nvl(used.bytes,0)/total.bytes*100  pctusd

 (total.file_bytes-nvl(tot_free.free_bytes,0))/total.bytes*100  pctusd

from

  (select

tablespace_name,

sum(bytes) file_bytes,

SUM(CASE WHEN maxbytes > bytes THEN maxbytes ELSE bytes END)       bytes

from

dba_data_files

group by

tablespace_name)

  total,

  (select

tablespace_name,

nvl(sum(bytes),0) free_bytes

from

dba_free_space

group by

tablespace_name) tot_free,

dba_free_space  free

where

  total.tablespace_name = free.tablespace_name(+)

and   total.tablespace_name = tot_free.tablespace_name(+)

group by

  total.tablespace_name,

  total.bytes,

  free_bytes,

  file_bytes

order by 1

/

col tsname heading "Temp Tablespace"

select

total.tablespace_name                       tsname,

total.bytes/1048576                         totsiz,

total.file_bytes/1048576                    filsiz

from (

select

tablespace_name,

sum(bytes) file_bytes,

SUM(CASE WHEN maxbytes > bytes THEN maxbytes ELSE bytes END)       bytes

from

dba_temp_files

group by

tablespace_name

) total

/

col name for a30 heading "ASM DiskGroup"

select name, free_mb, total_mb from v$asm_diskgroup order by 1;



RMAN Table PIT Recovery Notes

 --recover table and let rman import it in place. 

run {

recover table drs.test_me until scn 22044407

auxiliary destination '+SBD818_FRA_01';

}


--pluggable pdb option.

run {

recover table drs.test_me of pluggable database PDB2

until scn 22044407

auxiliary destination '/u02/CDB2/aux';

}


-- recover table and create import dump file.

run {

recover table drs.test_me until scn 22044407

auxiliary destination '+SBD818_FRA_01'

datapump destination '+SBD818_FRA_01/SBD818/tspitr'

dump file 'drs_test_me.dmp'

notableimport;

}


run {

recover table test_dummy.test_table until scn 861867

auxiliary destination '+SBD818_FRA_01'

datapump destination '+SBD818_FRA_01/dpdump_rman'

dump file 'test_my_drop.dmp'

notableimport;

}



create directory FRA_DATAPUMP as '+SBD818_FRA_01/dpdump_rman';

grant read, write on directory FRA_DATAPUMP to public;


create directory DP_LOG as '/srv/users/dba/oracle';

grant read, write on directory DP_LOG to public;


test_restore.par

DUMPFILE=test_my_drop.dmp

TABLES=test_dummy.test_table

LOGFILE=DP_LOG:impdp_test_dummy.log

JOB_NAME=test_import

DIRECTORY=FRA_DATAPUMP


oracle> impdp / parfile=test_dummy.par


Import: Release 19.0.0.0.0 - Production on Tue Nov 2 14:07:52 2021

Version 19.11.0.0.0


Copyright (c) 1982, 2019, Oracle and/or its affiliates.  All rights reserved.


Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Master table "OS_ORACLE"."TEST_IMPORT" successfully loaded/unloaded

Starting "OS_ORACLE"."TEST_IMPORT":  /******** parfile=test_dummy.par

Processing object type TABLE_EXPORT/TABLE/TABLE

Processing object type TABLE_EXPORT/TABLE/TABLE_DATA

. . imported "TEST_DUMMY"."TEST_TABLE"                       0 KB       0 rows

Processing object type TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS

Job "OS_ORACLE"."TEST_IMPORT" successfully completed at Tue Nov 2 14:07:56 2021 elapsed 0 00:00:04


RMAN Backup/Restore Notes

# these list and advice commands do not do much from what i have seen.

RMAN> LIST FAILURE;

RMAN> ADVISE FAILURE;

RMAN> REPAIR FAILURE;


RMAN> list backup summary;


RMAN> VALIDATE backupset 107929604, 107929605, 107929606;  (give all ids for CBK_FULL)


RMAN> RESTORE DATABASE VALIDATE;


RMAN> RESTORE ARCHIVELOG ALL VALIDATE;


RMAN> RESTORE DATABASE PREVIEW;


RMAN> run {

allocate channel t1 type SBT_TAPE;

VALIDATE DATABASE;   

release channel t1;

}


or VALIDATE PLUGGABLE DATABASE



RMAN> restore controlfile from autobackup;


RMAN> restore spfile from tag='CBK_FULL' to '$ORACLE_HOME/dbs';



SET UNTIL TIME "TO_DATE('2016-01-20 16:00:00','yyyy-mm-dd hh24:mi:ss')";

SET UNTIL SEQUENCE 1234 THREAD 1;



run {

allocate channel t1 type SBT_TAPE;

set until time "TO_DATE('2019-01-20 16:00:00','yyyy-mm-dd hh24:mi:ss')";

report schema device type sbt;

release channel t1;

}


[NOMOUNT MODE]

RMAN> run {

allocate channel t1 type SBT_TAPE;

set until time "TO_DATE('2019-01-20 16:00:00','yyyy-mm-dd hh24:mi:ss')";

RESTORE SPFILE TO PFILE '/opt/oracle/admin/<SID>/init<SID>.ora';

RESTORE CONTROLFILE TO  '/opt/oracle/admin/<SID>/ctrl01_temp.ora';

release channel t1;

}


[NOMOUNT MODE]

RMAN> startup nomount;

RMAN> RUN {

  SET UNTIL SEQUENCE 12345 THREAD 1;

  RESTORE CONTROLFILE ;

  ALTER DATABASE MOUNT;

  RESTORE DATABASE;

  RECOVER DATABASE;  # recovers through log 12344

  ALTER DATABASE OPEN RESETLOGS;

}


[MOUNT MODE]

RMAN> startup mount;

RMAN> run {

allocate channel t1 type SBT_TAPE;

allocate channel t2 type SBT_TAPE;

allocate channel t3 type SBT_TAPE;

set until time "TO_DATE('2019-01-20 16:00:00','yyyy-mm-dd hh24:mi:ss')";

restore database;

recover database;

release channel t1;

release channel t2;

release channel t3;

}


[PIT RECOVERY] [mount mode]

RMAN> FLASHBACK DATABASE TO SCN 12345678910;


RMAN> RECOVER DATABASE UNTIL TIME 'YYYY-MM-DD:HH24:MI:SS'; #need quotes


RMAN> RECOVER DATABASE UNTIL SCN 12345678910;


RMAN> RECOVER DATABASE UNTIL SEQUENCE 12345 THREAD 1;



[RECOVERY UNTIL LAST AVAILABLE ARCHIVE]

RMAN> recover database until cancel;



[RECOVER UNTIL RESTORE POINT]

STARTUP MOUNT;

RUN

{

  SET UNTIL RESTORE POINT 'before_upgrade';

  RESTORE DATABASE;

  RECOVER DATABASE;

  ALTER DATABASE OPEN RESETLOGS;

}



RMAN> alter database open resetlogs;