log_archive_dest_1

Hoy vamos a ver una entrada un tanto extraña que me ha ocurrido en alguna base de datos.

A la hora de configurar el archivado, el parametro que tenia era 


alter system set log_archive_dest_1=
'LOCATION=USE_DB_RECOVERY_FILE_DEST,valid_for=(ALL_LOGFILES, ALL_ROLES)';

Sin embargo,  esto fallaba no dejando los archivers en a ubicacion correcta. 

¿como lo solcione?

Algo tan extraño como cambiandolo por una de estas dos maneras 


alter system set log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST VALID_FOR=(ALL_LOGFILES, ALL_ROLES)'

alter system set log_archive_dest_1='LOCATION=USE_DB_RECOVERY_FILE_DEST','VALID_FOR=(ALL_LOGFILES, ALL_ROLES)'

Como podeis ver , la diferencia es muy sutil, pero , igual puede servirle a alguien mas

Version del parcheado de la base de datos

Hoy vamos a ver otra de estas entradas para dummies utiles en el dia a dia.
Como sabemos en que version de parcheado nos encontramos?

La primera opcion y mas sencilla es la del uso del binario del sistema operativo opatch, pero , como podemos estar seguros de que el parche/psu se ha ejecutado correctamente y se ha aplicado tambien la parte SQL

Oracle 11g

Si estamos en la version 11g deberemos de hacerlo consultando la tabla del diccionario sys.registry$history

SET LINESIZE 180 PAGESIZE 90 
COLUMN FECHA FORMAT A18
COLUMN action FORMAT A20
COLUMN version FORMAT A10
COLUMN comments FORMAT A30
COLUMN bundle_series FORMAT A10
SELECT TO_CHAR(action_time, 'YYYY-MM-DD HH24:MI') AS FECHA,
       action,
       namespace,
       version,
       comments,
       bundle_series
FROM   sys.registry$history
ORDER by action_time;

Lo que nos devolvera algo similar a :

FECHA              ACTION               NAMESPACE            VERSION    COMMENTS                       BUNDLE_SER
------------------ -------------------- -------------------- ---------- ------------------------------ ----------
07-JAN-2017 15:21  APPLY                SERVER               11.2.0.3   PSU 11.2.0.3.15                PSU
01-DEC-2017 18:59  UPGRADE              SERVER               11.2.0.4.0 Upgraded from 11.2.0.3.0
01-DEC-2017 19:00  APPLY                SERVER               11.2.0.4   PSU 11.2.0.4.171017            PSU

Oracle 12c

Cuando estamos en la version 12c, tendremos dos maneras de encontrar esta informacion:

Preguntando a DBA_REGISTRY_SQLPATCH

La consulta sera muy similar a la anterior, pero en ved de preguntar a el dicionario sys.registry$history, lo haremos a la tabla DBA_REGISTRY_SQLPATCH



SET LINESIZE 180 PAGESIZE 90 
COLUMN FECHA FORMAT A20
COLUMN action FORMAT A10
COLUMN status FORMAT A20
COLUMN description FORMAT A90
COLUMN version FORMAT A10
COLUMN bundle_series FORMAT A10
SELECT TO_CHAR(action_time, 'YYYY-MM-DD HH24:MI:SS') AS action_time,
       action,
       status,
       description,
       version,
       patch_id,
       bundle_series
FROM   sys.dba_registry_sqlpatch
ORDER by action_time;

Lo que nos devolvera algo similar a

ACTION_TIME          ACTION     STATUS     DESCRIPTION                              VERSION      PATCH_ID BUNDLE_SER
-------------------- ---------- ---------- ---------------------------------------- ---------- ---------- ----------
07-MAR-2018 21:37:51 APPLY      SUCCESS    Database Patch Set Update : 12.1.0.2.4  12.1.0.2     20831110 PSU
                                         (20831110)

Mediante el package dbms_qopatch

En la version 12c tenemos el nuevo datapatch en los parcheados, la informacion de los parches de la base de datos esta tambien accesible con el package dbms_qopatch.
Esto ya lo vimos en la entrada Obtener los parches instalados en la base de datos CDB que venia a decir :

 
 set serverout on
exec dbms_qopatch.get_sqlpatch_status;

Lo que nos devuelve

Patch Id : 25171037
        Action : APPLY
        Action Time : 14-JUN-2017 23:09:33
        Description : DATABASE PATCH SET UPDATE 12.1.0.2.170418
        Logfile :
/u01/app/oracle/cfgtoollogs/sqlpatch/25171037/21099266/25171037_apply_SID_2017Jun14_23_09_20.log
        Status : SUCCESS
PL/SQL procedure successfully completed.

Sobre el uso de dbms_qopatch tenemos la URL hay una URL Como saber si un parche esta aplicado en la BBDD que tiene consultas muy utiles para obtener informacion de la base de datos (inventario,paches…)

Esta informacion ha sido obtenido en su totalidad de las URLS:

Restaurando archivelogs

Hoy vamos a volver a las entradas para dummies .
En esta entrada vamos a ver en una entrada muy rapida algunas maneras de restaurar archivelogs.

Desde numero de secuencia

La primera y mas comun recuperar un archiver en conreto

RUN
{
SET ARCHIVELOG DESTINATION TO '/sitiotemporal';
restore archivelog  logseq=8619;
}

Podemos hacerlo tambien con un rango con

restore archivelog from sequence 8619 until sequence 8639;

o tambien con

restore archivelog sequence between 8619 and  8639;

De un dia atras

Esta puede ser muy comoda a la hora de incrementales

RUN
{ 
SET ARCHIVELOG DESTINATION TO '/sitiotemporal';
ALLOCATE CHANNEL d1 DEVICE TYPE disk;
 restore ARCHIVELOG FROM TIME 'SYSDATE-1' UNTIL TIME 'SYSDATE';
}

Tambien podriamos indicarlo

restore ARCHIVELOG FROM TIME "to_date('11/04/18 00:00:01','DD/MM/YY HH24:MI:SS')
UNTIL TIME 'SYSDATE';

En RAC

En un rac es igual que en los anteriores, pero deberemos de indicar el numero de thread que nos corresponde

{
SET ARCHIVELOG DESTINATION TO '/sitiotemporal'
restore archivelog from logseq=8619 until logseq=8632 thread=2;
}

Consultas basicas para lob segments

Hoy vamos a otra de estas entradas para dummies que recopilan SQL utles, en este caso para tratar con los lobs.
Las variables de formateo del sqlplus para estas consultas serian

set linesize 180 pagesize 900
column SEGMENT_NAME format a40;
column TABLE_NAME format a60;
column TABLESPACE_NAME format a30;
column owner format a20;

Lista de los lobs mas grandes y lo que ocupan para el esquema

select  e.owner,l.tablespace_name,
l.table_name,
l.segment_name,sum(e.bytes/(1024*1024*1024)) Gb
from dba_extents e,dba_lobs  l
where
	e.owner = l.owner
	and 	e.segment_name = l.segment_name
	and 	e.OWNER='ESQUEMA'
	and 	e.segment_type = 'LOBSEGMENT'
     group by  
     e.owner,l.tablespace_name,
    l.table_name,
     l.segment_name 
     order by Gb desc ;

Obtener los datos (esquema,tabla y columna) de un LOB determinado

select OWNER,TABLE_NAME,COLUMN_NAME from dba_lobs
 where SEGMENT_NAME='SYS_LOBXXXXXX$$';

Bytes ocupados por un LOB

select sum(dbms_lob.getlength (COLUMNA))/1024/1024 Mb ESQUEMA.TABLA;
o bien 

select bytes/1024/1024 Mb
from dba_segments where segment_name ='SYS_LOBXXXXXX$$' ;

o esta mas completa

set serveroutput on
declare
     l_segment_size_blocks NUMBER;
     l_segment_size_bytes NUMBER;
     l_used_blocks NUMBER;
     l_used_bytes NUMBER;
     l_expired_blocks NUMBER;
     l_expired_bytes NUMBER;
     l_unexpired_blocks NUMBER;
     l_unexpired_bytes NUMBER;
     l_unused_blocks NUMBER;
     l_unused_bytes NUMBER;
     l_non_data_blocks NUMBER;
     l_non_data_bytes NUMBER;
 BEGIN
	DBMS_SPACE.SPACE_USAGE(
   	  segment_owner =>'ESQUEMA',
	  segment_name => 'SYS_LOB0000227238C00034$$',
	  segment_type => 'LOB',
	  segment_size_blocks => l_segment_size_blocks,
	  segment_size_bytes => l_segment_size_bytes,
	  used_blocks => l_used_blocks,
	  used_bytes => l_used_bytes,
	  expired_blocks => l_expired_blocks,
	  expired_bytes => l_expired_bytes,
	  unexpired_blocks => l_unexpired_blocks,
	  unexpired_bytes => l_unexpired_bytes
           );
      l_unused_blocks := l_segment_size_blocks - (l_used_blocks + l_expired_blocks + l_unexpired_blocks);
      l_unused_bytes := l_segment_size_bytes - (l_used_bytes + l_expired_bytes + l_unexpired_bytes);
	  l_non_data_blocks := l_unused_blocks + l_expired_blocks + l_unexpired_blocks;
	  l_non_data_bytes :=  l_unused_bytes + l_expired_bytes + l_unexpired_bytes;
	  DBMS_OUTPUT.ENABLE;
	   DBMS_OUTPUT.PUT_LINE(' Segment Blocks/Bytes   = '||l_segment_size_blocks||' / '||l_segment_size_bytes);
	  DBMS_OUTPUT.PUT_LINE(' Unused Blocks/Bytes    = '||l_unused_blocks||' / '||l_unused_bytes);
	  DBMS_OUTPUT.PUT_LINE(' Used Blocks/Bytes      = '||l_used_blocks||' / '||l_used_bytes);
	  DBMS_OUTPUT.PUT_LINE(' Expired Blocks/Bytes   = '||l_expired_blocks||' / '||l_expired_bytes);
	  DBMS_OUTPUT.PUT_LINE(' Unexpired Blocks/Bytes = '||l_unexpired_blocks||' / '||l_unexpired_bytes);
	  DBMS_OUTPUT.PUT_LINE('===========================================================================');
	  DBMS_OUTPUT.PUT_LINE(' NON Data Blocks/Bytes  = '||l_non_data_blocks||' / '||l_non_data_bytes);
 END;
 /

Mover una tabla con Lobs ( para hacer shrink)

Este metodo implica bloqueo durante el traslado

ALTER TABLE ESQUEMA.TABLA MOVETABLESPACE NUEVOTABLESPACE;
Y para cada uno de los lobs de la tabla 

ALTER TABLE ESQUEMA.TABLA MOVE LOB(COLUMNA) STORE AS SECUREFILE (TABLESPACE NUEVOTABLESPACE);

Apagando instancias

Hoy vamos aver un pequeño script que nos facilitara el apagar todas las bases de datos de un servidor aunque no esten incluidas en el rac

Si nos fijamos un poco en el script, podemos ver como las funciones de apagado estan comentadas, esto es una mera medida de seguridad para evitar posibles errrores de «copy & paste »

[cc lang=»shell»]
#!/bin/bash
#
#
# Name: stop_oratab_alone.sh
# Desc: Stops all oratab databases (not RAC)

function estado
{
echo » The status of $ORACLE_SID is:»
sqlplus -s «/as sysdba» << EOF 2>>/dev/null
set linesize 400;
column host_name format a30;
column instance_name format a20;
column Started format a25;
column uptime format a60;
select
host_name,
instance_name,
to_char(startup_time,’DD-MON-YYYY HH24:MI:SS’) Started,
‘Uptime : ‘ || floor(sysdate – startup_time) || ‘ days(s) ‘ ||
trunc( 24*((sysdate-startup_time) –
trunc(sysdate-startup_time))) || ‘ hour(s) ‘ ||
mod(trunc(1440*((sysdate-startup_time) –
trunc(sysdate-startup_time))), 60) ||’ minute(s) ‘ ||
mod(trunc(86400*((sysdate-startup_time) –
trunc(sysdate-startup_time))), 60) ||’ seconds’ uptime
from
sys.v_\$instance;
EOF

}

function apagar
{
#srvctl stop database -d ${ORACLE_DB} ${ORACLE_SID} -stopoption IMMEDIATE

}

function test_status
{
srvctl status database -d ${ORACLE_DB} ${ORACLE_SID} RED=’\033[0;31m’
GREEN=’\033[0;32m’
NC=’\033[0m’
COUNT=` ps -ef |grep smon |grep -v grep | grep $ORACLE_SID|wc -l `
if [ ${COUNT} -ne 0 ]; then
printf «${RED}FAIL${NC} There are ${COUNT} smon_${ORACLE_SID} processes\n»
else
printf «${GREEN} OK ${NC} There is not any smon_${ORACLE_SID} process\n»
fi
}

export ORAENV_ASK=NO
export NODO=`hostname -a`
for i in `cat /etc/oratab |tr ‘:’ ‘ ‘ |awk ‘{ print ($1)’}|grep -v «#»|grep -v «+»|grep -v «-» |grep -v [1-9]`
do
clear
ORACLE_DB=$i
ORACLE_SID=$i
. oraenv 2>/dev/null
export ORACLE_SID=`ps -ef|grep pmon|grep $i |tr ‘_’ ‘ ‘|awk ‘{ print ($10)’}`
echo «New oracle SID=$ORACLE_SID»
estado;
#apagar
test_status;

read
echo «[press any key]»
done

[/cc]

Este script tiene una particularidad, y es que no esta pensado para usarse en RAC, para usarse en un RAC solamente habra que modificar la sintaxsis de apagado incluyendo el instance name y el nodo