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

Problemas con optachauto y resolucion de nombres (error code 238)

Hoy vamos a ver una entrada rápida

Recientemente me he encontrado con el error code 238 intentando llevar a cabo la aplicación de un parche con el optachauto.

Al intentar llevar a cabo el parcheado me devolvía el siguiente error:

root:$GRID_HOME/OPatch/opatchauto apply $PARCHES/26610308 
OPatchauto session is initiated at Sun Nov 18 15:56:14 2017 

Patch version not found


OPatchauto session completed atSun Nov 18 15:56:20 2017 
Time taken to complete the session 0 minute, 7 seconds 

opatchauto bootstrapping failed with error code 238. 

La primera conclusion que debemos de sacar de esto. siempre hay que hacer el analize antes de la aplicacion, ya que de esa manera habríamos comprobado el error .

Tras mucho buscar en la web de soporte y abrir un caso con Oracle, encontramos el problema.

El fichero /etc/hosts de mi servidor tenia mas de dos entradas, supongamos que fuese algo similar a:


10.0.0.1  SERVER server server.dominio  server-vip.dominio 

Si desde el sistema operativo preguntábamos por cualquiera de las 4 entradas, el servidor funcionaba correctamente.

Sin embargo, al cambiar esa linea por


10.0.0.1  server server.dominio
10.0.0.1  SERVER  SERVER.dominio 
10.0.0.1  serve-vip  server-vip.dominio 

Todo volvió a funcionar a la perfeccion.

Un expediente X que nos sirve para recordar que no todo vale a la hora de solcitar las instalaciones a los equipos responsables de los sistemas operativos, las nuevas herramientas de gestion de los componentes de oracle (opatchauto,datapatch …) son muy potentes, pero no dejan de ser componentes externos a la base de datos que requieren de configuraciones correctas que, desgraciadamente no suelen estar tan documentadas como los prerrequisitos del GRID, RAC o Base de datos, por lo que siempre deberemos de velar por que los sistemas operativos donde se encuentran nuestros motores esten prefectametne configurados

Trucos para crear un dataguard standby

Si consultamos la documentación de Oracle la creación de un datagurard es algo facilísimo, pero a la hora de la verdad, siempre hay pequeños flecos de configuración antes de la creación que es lo que nos puede traer de cabeza, vamos a ver en esta entrada algunos puntos que mirar antes de empezar para que todo funcione.

Suponemos que :

  • EL SID de la base de datos va a ser cdbtest
  • A la base de datos primaria la llamaremos primary , su nombre único será cdbtest
  • A la base de datos standby la llamaremos standby ,su nombre único será cdbtest_sdby

Pasos a llevar a cabo en primary

Se gun la documentación de Oracle, debería de bastar con:

, pero siempre hay cosas que podemos ir haciendo para que todo vaya a la primera

Activar el standby file management

Mediante esta opción los cambios que llevemos a cabo en la primary database se llevaran a cabo en la standby

alter system set STANDBY_FILE_MANAGEMENT=AUTO ;

Crear grupos de standby redo logs

Estos grupos serán necesarios en standby, si los tenemos creados en primary ademas solucionaremos antes de que ocurran los problemas en caso de switchover.

La sintaxis es igual que la de la creación de un grupo normal añadiendo standby

alter database add standby logfile group 4  '/u01/app/oracle/oradata/cdbtest/standby_redo04.log' size 52428800;

Hay que crear un grupo de standby redo log file mas que los grupos de redo logs normales.

Configurar el tnsnames del servidor

Este es uno de los puntos importantes, el servidor debe de ser capaz de acceder por oraclenet al standby.
Dado que los dos SID van a ser iguales, aconsejamos el poner una entrada clara en el listener.ora, en nuestro caso los llamaremos exactamente igual que el DB_UNIQU_NAME que es CDBTEST_STDBY

CDBTEST_STANDBY =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = standby.pamplona.name)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = cdbtest)
    )
  )

Además de esta entrada, deberá de haber una entrada para el LOCAL_LISTENER,la teoría indica que esto ya debería de estar configurado, pero la realidad a veces es distinta, por lo que nos aseguraremos que la variable LOCAL_LISTENER de nuestra base de datos este correctamente configurada y tenga su entrada en el nsnames.ora .


LISTENER_CDBTEST =
  (ADDRESS = (PROTOCOL = TCP)(HOST = alone.pamplona.name)(PORT = 1521))

Configurar parametros en spfile

Antes de proseguir, es obligatorio el uso de spfile , la creación de la replica va a ser mediante RMAN, por lo que, en caso de usar file fallaría la creación del spfile en standby

Los parámetros que hemos de poner son:

DB_UNIQUE_NAME

Este parámetro no es obligatorio en el primary, pero es recomendable, por lo que lo pondremos

alter system set db_unique_name='cdbtest' scope=spfile sid='*';

LOG_ARCHIVE_CONFIG

LOG_ARCHIVE_CONFIG habilita o deshabita la recepcion/envio de los redo, pero lo que realmente nos interesa es que especifica para cada una de las bases de datos del Dataguard los nombres únicos de las mismas (DB_UNIQUE_NAME)

alter system LOG_ARCHIVE_CONFIG='DG_CONFIG=(cdbtest,cdbtest_stby)'

LOG_ARCHIVE_DEST_X

Otro de los valores que cambiaremos es la ubicación de los redo logs, aquí indicaremos donde va el primary y el standby, así como los casos.

ALTER SYSTEM SET LOG_ARCHIVE_DEST_1= 'LOCATION=/u01/app/oracle/oradata/cdbtest/archivelog
  VALID_FOR=(ALL_LOGFILES,ALL_ROLES)';
ALTER SYSTEM SET log_archive_dest_2='service=CDBTEST_STANDBY ASYNC NOAFFIRM delay=0 optional compression=disable max_failure=0 max_connections=1 reopen=300 net_timeout=30 DB_UNIQUE_NAME=cdbtest_sdby valid_for=(online_logfile,all_roles)' ;

Configuraciones en el servidor de Standby

Estas configuraciones son seguramente las que mas nos hagan fallar en el proceso, ya que en muchos documentos se dejan como algo que se asume ya está.
Las configuraciones son:

Configuraciones de tnsnames.ora

Este es posiblemente el fichero que vaya a marcar el éxito de nuestra acción a la primera, deberá de contar con las lineas:

  • LOCAL_LISTENER deberemos de tener una entrada distinta a la de producción que fijaremos en la BBDD standby
  • BBDD primaria debemos de tener una entrada que apunte a la BBDD primaria
  • BBDD standbydebemos de tener una entrada que apunte a la BBDD standby

LISTENER_CDBTEST_STANDBY =
(ADDRESS = (PROTOCOL = TCP)(HOST = standby.pamplona.name)(PORT = 1521))

CDBTEST_PRIMARY =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = alone.pamplona.name)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = cdbtest)
)
)

CDBTEST,CDBTEST_STANDBY =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = standby.pamplona.name)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SID = cdbtest)
)
)

IMPORTANTE:Si miramos con atención el código que hemos puesto, veremos como el truco es que en el nodo standby la conexión a cdbtest será a si mismo, denotando el primario con otro nombre.

Configuraciones estática del listener

Además de la configuración standard del Listener, deberemos de definir una linea estática con la definición del standby.

# Configuracion estatica para el Dataguard
SID_LIST_LISTENER=
  (SID_LIST=
    (SID_DESC= (DB_UNIQUE_NAME=cdbtest_sandby) (ORACLE_HOME=/u01/app/oracle/product/12.1.0/dbhome_1) 
(SID_NAME=cdbtest))

Si no tenemos esta opción, al intentar conectar con el rman obtendremos el error

RMAN-04006: error from auxiliary database: ORA-12528: TNS:listener: all appropriate instances are blocking new connections

Creación de las rutas físicas de la BBDD

En el caso como es el del ejemplo que haya rutas físicas para los datafiles, deberán de estar creadas en el servidor de standby con los permisos necesarios.

Copiado de fichero init.ora

Aunque hemos dicho que es necesario que la base de datos primaria necesitaba de un fichero sprite, para poder arrancar nuestra base de datos de dataguard , la base de datos standby necesitará un init.ora mínimo para arrancar.
Este init.ora va a ser cambiado por el spfile que recuperaremos de la primary,
Es importante que tengamos:

  • db_name
  • db_unique_name
  • local_listener

El resto como decimos lo eliminará substituirá el proceso.

*.audit_file_dest='/u01/app/oracle/admin/cdbtest/adump'
*.audit_trail='db'
*.compatible='12.1.0.2.0'
*.db_block_size=8192
*.db_domain=''
*.db_name='cdbtest'
*.db_unique_name='cdbtest_sdby'
*.diagnostic_dest='/u01/app/oracle'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=cdbtestXDB)'
*.enable_pluggable_database=true
*.local_listener='LISTENER_CDBTEST_STANDBY'
*.log_archive_config='DG_CONFIG=(cdbtest,cdbtest_sdby)'
*.memory_target=4000m
*.open_cursors=300
*.processes=300
*.remote_login_passwordfile='EXCLUSIVE'
*.standby_file_management='AUTO'
*.undo_tablespace='UNDOTBS1'

Creación de fichero de duplicado

Llegamos al punto importante, el fichero de duplicado de aman.
Este proceso que era bastante costoso en las versiones 9 y 10 se ha facilitado muchísimo en la 11 y 12.

El fichero viene a ser algo así

connect target sys/XXX@cdbtest_primary
connect auxiliary sys/XXX@cdbtest
DUPLICATE TARGET DATABASE
  FOR STANDBY
  FROM ACTIVE DATABASE
  DORECOVER
NOFILENAMECHECK
  SPFILE
	SET db_unique_name="cdbtest_sdby"  comment "Base de datos sandby"
	SET LOCAL_LISTENER="LISTENER_CDBTEST_STANDBY"
	SET standby_file_management='AUTO'
	set log_file_name_convert='/u01/app/oracle/oradata/cdbtest/','/u01/app/oracle/oradata/cdbtest/'

Y los puntos importantes son:

  • NOFILENAMECHECK Esto nos dejará todos los ficheros exactamente como en la primary
  • Apartado set Aqui le decimos lo que va a cambiar del spfile respecto de la original, nosotros cambiamos:
    • db_unique_name. Indicamos el unique name de la standby
    • LOCAL_LISTENER Este es importante para que encuentre el listener de la maquina de la standby
    • log_file_name_convert La teoría indica que no deberíamos de tener que indicar este parámetro, pero en diversas pruebas he tenido problemas con los redo log files, mediante esta cláusula, indicándole el path de los redo log Files por duplicado (para que no cambie nada) los crea correctamente

Duplicacion

Con esto solamente nos queda el proceso de duplicación, que ya es algo tan sencillo como ejecutar en el servidor de standby

#!/bin/bash
SET ORACLE_SID=cdbtest 
sqlplus "/as sysdba" << EOF
startup nomount;
exit;
EOF
rman cmdfile comandos_rman.cmd 

Obtener los parches instalados en la base de datos /CBD

Hoy vamos a ver una entrada muy rápida saber como ver el nivel de parcheado de una máquina.

Con el nuevo modelo de datapatch y los pdb/cbd la propia base de datos /contenedor necesita saber en que nivel de parcheado se encuentra, para ello tenemos un nuevo conjunto de librerías en el paquete DBMS_QOPATCH que informan de los parches que se han aplicado en la base de datos.
En nuestro caso, vamos a ver la llamada dbms_qopatch.get_sqlpatch_status;

[oracle@TEST] $ sqlplus "/as sysdba"
SQL*Plus: Release 12.1.0.2.0 Production on Fri Jun 16 16:54:59 2017
SQL>  set serverout on
SQL> exec dbms_qopatch.get_sqlpatch_status;

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.


Aquí podemos ver como , a esta base de datos sele ha aplicado el PATCH SET UPDATE 12.1.0.2.170418
Pero puede darse el caso de que , se aplique un parche sobre la infraestructura, o sobre los binarios sin aplicarse sobre el motor.

IMPORTANTE

Así pues recordar que , ahora, deberemos de mirar

  • Opatch lsinventory para ver el nivel de parcheado del motor
  • bms_qopatch.get_sqlpatch_status Para ver los parches aplicados sobre tu cbd o base de datos

Informacion en el arranque

“Dumping current patch information” in Alert Log 12c can lead to a misinterpretation

Acciones en sys.aud$

Hoy vamos a ver una entrada rápida y sencilla sobre una de las tablas que mas vamos a usar en la auditoría.

Cuando preguntamos a la tabla sys.aud$ por un evento ( por ejemplo ver los logins), lo hacemos en base a un código del campo action#.
pero , ¿cual es el listado de codigos y la descripcion?
La respuesta es muy sencilla, y se encuentra en la tabla audit_actions
Si queremos saber el listado de descripciones para nuestra tabla solo deberemos de hacer

SELECT action, name 
  FROM audit_actions
ORDER BY 1;

Otro ejemplo facil de uso, es, si queremos saber el código de accion para un borrado de usuario,lo podemos obtener con :

SELECT action 
          FROM audit_actions
        WHERE name='DROP USER';

Com veis, una tabla muy util y tremendamente sencilla de consultar