miércoles, 31 de marzo de 2010

Como copiar/clonar de forma rápida un base de datos?

La tarea de clonación de de una base de datos es algo bastante frecuente para un DBA ya que muchas veces es necesario tener ambientes de desarrollo o testeo actualizados con los datos que tenemos en ambientes productivos. Por lo tanto y al ser algo frecuente sería bueno contar con un procedimiento rápido y fácil para llevarlo a cabo.

Para realizar dicho procedimiento vamos a realizar una serie de pasos que detallo a continuación:

1- En nuestra base origen (a partir de ahora PROD) nos conectamos al SQL*Plus y ejecutamos:

SQL> ALTER DATABASE BACKUP CONTROLFILE TO TRACE;

Con esta sentencia obtenemos la sintaxis para realizar el “CREATE CONTROLFILE” (este archivo lo podemos encontrar dentro del directorio de trace, user_dump_dest). El archivo cuenta con la siguiente forma:

STARTUP NOMOUNT
CREATE CONTROLFILE REUSE DATABASE "PROD" NORESETLOGS
NOARCHIVELOG
MAXLOGFILES 12
MAXLOGMEMBERS 2
MAXDATAFILES 280
MAXINSTANCES 1
MAXLOGHISTORY 120
LOGFILE
GROUP 1 ('/u01/oradata/PROD/log1a.dbf',
'/u01/oradata/PROD/log1b.dbf') SIZE 50M,
GROUP 2 ('/u01/oradata/PROD/log2a.dbf',
'/u04/oradata/PROD/log2b.dbf') SIZE 50M
DATAFILE
'/u01/oradata/PROD/system01.dbf',
'/u01/oradata/PROD/prueba.dbf'
;
# Recovery is required if any of the datafiles are restored
# backups, or if the last shutdown was not normal or immediate.
RECOVER DATABASE
# Database can now be opened normally.
ALTER DATABASE OPEN;


2- Realizamos un shutdown en la base PROD

SQL> SHUTDOWN IMMEDIATE;

3- Ahora es momento de copiar todos los ‘data files’ y ‘log files’ al nuevo server o a la nueva ubicación. Si cambiamos el nombre de los ‘data files’ debemos realizar también los cambios en el controlfile. A modo de ejemplo supongamos que tenemos todos los ‘data files’ dentro de /u01/oradata/PROD/ y los vamos a llevar al servidor TESTER en la ubicación /u01/oradata/TEST/

rcp /u01/oradata/PROD/* TESTER:/u01/oradata/TEST

4- Copiar el archivo que obtuvimos en el punto 1 (de ahora en adelante lo llamaremos clona.sql) y modificar la siguiente línea

CREATE CONTROLFILE REUSE DATABASE "PROD" NORESETLOGS

Por la siguiente línea

CREATE CONTROLFILE SET DATABASE "TEST" RESETLOGS

5- Quitar las siguientes líneas de clona.sql:

- RECOVER DATABASE

- ALTER DATABASE OPEN


6- Siguiendo con los cambios en clona.sql, es el turno de modificar el directorio de los ‘data files’ y ‘log files’, a modo de ejemplo:

'/u01/oradata/PROD/system01.dbf'
'/u01/oradata/PROD/prueba.dbf'


Por las siguientes línea

'/u01/oradata/TEST/system01.dbf'
'/u01/oradata/TEST/prueba.dbf'


7- En este paso podríamos crear los directorios necesarios para los ´dump´ de Oracle, a modo de ejemplo:

TEST@TESTER ] cd $ORACLE_BASE/admin
TEST@TESTER ] mkdir TEST
TEST@TESTER ] cd TEST
TEST@TESTER ] mkdir bdump
TEST@TESTER ] mkdir cdump
TEST@TESTER ] mkdir udump
TEST@TESTER ] mkdir pfile


8- Copiar el archivo de parámetro (pfile.ora), a modo de ejemplo

cd $ORACLE_BASE/admin/PROD/pfile/
rcp *.ora TESTER:/u01/oracle/admin/TEST/pfile


9- Corremos desde el sqlplus en TESTER el archivo clona.sql

SQL> @db_create_controlfile.sql

10- Luego deberíamos abrir la base de datos.

Espero que les haya servido

Saludos!
Gondalf

jueves, 25 de marzo de 2010

Consultas a la DBA_VIEWS

Como muchos saben, realizar una consulta a la vista dba_views para buscar un texto en particular que posea una vista no es una tarea sencilla. Esto se debe a que el campo TEXT de la vista es de tipo LONG por lo que no podemos hacer una comparación en la clausula where ya que nos arrojaría el siguiente error:

SQL> select * from dba_views where text like '%PRUEBA%'

ORA-00932: inconsistent datatypes: expected NUMBER got LONG

Para resolver este problema a continuación vamos a ver dos posibles soluciones:

1- La primera es a través de un script con el cual vamos a poder ver las vistas que contengan el texto que necesitemos buscar

BEGIN
FOR r IN (SELECT owner, view_name, text FROM dba_views) LOOP
IF r.text LIKE '%PRUEBA%' THEN
dbms_output.put_line(r.view_name);
END IF;
END LOOP;
END;
/


En este caso con la creación de un cursor podemos realizar la búsqueda que necesitamos del campo TEXT.

2- La segunda alternativa es copiar los datos a una tabla “temporal”, convirtiendo los datos LONG en CLOBs, para esto podemos hacer lo siguiente:

SQL> create table my_dba_views (owner, view_name, text) as select owner, view_name, to_lob(text) from dba_views;

Table created

Ahora podemos realizar la consulta normalmente

SQL> select view_name from my_dba_views where upper(text) like '%PRUEBA%';


Espero les haya servido

Saludos!
Gondalf

domingo, 21 de marzo de 2010

Usando SRVCTL

La herramienta srvctl es la que Oracle nos recomienda que utilicemos para poder interactuar con el CRS y con la registry del cluster. Esta herramienta podemos decir que está muy bien documentada y es bastante amigable para utilizar.
Si utilizamos otras herramientas que no están soportadas por Oracle corremos el riesgo de que se dañe el archivo OCR.

El formato básico para de este comando es el siguiente

srvctl <'command'> <'target'> [options]

- En donde [options] puede ser cualquiera de la siguiente lista:

enable|disable|start|stop|relocate|status|add|remove|modify|getenv|setenv|
unsetenv|config


- Y donde <'target'> puede ser o bien una base de datos, una instancia, un servicio, una instancia de ASM o bien "nodeapps" Aplicaciones del nodo por darle una traducción, estas son los siguientes procesos: la VIP, ONS, GSD, y el listener junto a las aplicaciones definidas dentro del cluster de Oracle)

En la siguiente tabla tenemos un resumen de los posibles comandos a ejecutar con SRVCTL:


Como podemos ver, son muchas las sentencias a recordar, y quizá sea una tarea un poco difícil el recordar todas, por lo que para facilitarnos esa tarea tenemos:

- srvctl –help tiene la siguiente salida

Usage: srvctl <'command'> <'object'> [<'options'>]
command: enable|disable|start|stop|relocate|status|add|remove|modify|getenv|setenv|unsetenv|config
objects: database|instance|service|nodeapps|asm|listener
For detailed help on each command and object and its options use:
srvctl <'command'> <'object'> -h
-

srvctl –h muestra la información anterior pero con mayor detalle.

ALGUNOS EJEMPLOS

- Levantar la instancia PRUEBA1 de la base PRUEBA.

[oracle@Testeo1 oracle]$ srvctl start instance -d PRUEBA -i PRUEBA1

- Bajamos la base PRUEBA: para esto bajamos todas sus instancias y sus servicios en todos los nodos.

[oracle@Testeo1 oracle]$ srvctl stop database -d PRUEBA

- Bajamos el “nodeapps” en el nodo Testeo1

[oracle@Testeo1 oracle]$ srvctl stop nodeapps -n Testeo1

- Agregar una nueva instancia a la base PRUEBA, en este caso PRUEBA3, la cual está corriendo en el nodo Testeo1.

[oracle@Testeo1 oracle]$ srvctl add instance -d PRUEBA -i PRUEBA3 -n Testeo1

- Cambiar la VIP (IP virtual) en uno de los nodos del RAC

[oracle@Testeo1 oracle]$ srvctl modify nodeapps -A new_address

- Deshabilitamos la instancia de ASM sobre Testeo1.

[oracle@Testeo1 oracle]$ srvctl disable asm -n Testeo1

Espero que les haya servido.

Saludos!
Gondalf

sábado, 13 de marzo de 2010

Indices Virtuales

Vamos a intentar explicar un poco que son y para sirven los índices virtuales en Oracle.

El propósito de este tipo de índices es el hecho de simular la existencia de uno real, pero sin la necesidad de su construcción, nos ayudaran a determinar utilizando CBO (evaluación del plan de ejecución basada en costos) si es bueno o no su creación “física”. Su definición se encuentra en el diccionario de datos (en ciertas vistas) pero si realizamos una consulta en la vista DBA_SEGMENTS no lo encontraremos.

Oracle posee una cláusula oculta mediante la cual nos permitirá crear este tipo de índices, la misma es “nosegment”.
Además de conocer esta clausula debemos tener en cuenta que para poder utilizarlos es necesario setear el parámetro oculto “_use_nosegment_indexes”

La creación de los mismos se realiza de la siguiente manera:

SQL> CREATE unique INDEX VIRTUAL_PRUEBA on table_name(col_name) NOSEGMENT;

Y para utilizarlo, como dijimos seteamos la siguiente variable:

SQL> ALTER SESSION SET "_use_nosegment_indexes" = TRUE;

Veamos como buscamos el índice que creamos en las vistas del diccionario de datos:

SQL> select segment_name, segment_type, bytes
2 from dba_segments
3 where segment_name = 'VIRTUAL_PRUEBA';


no rows selected

SQL> select object_name, object_type, status
2 from dba_objects
3 where object_name = 'VIRTUAL_PRUEBA;


OBJECT_NAME |OBJECT_TYPE |STATUS
------------------|-----------------|---------------
VIRTUAL_PRUEBA |INDEX |VALID

SQL> select index_name, index_type, status
2 from dba_indexes
3 where index_name = 'VIRTUAL_PRUEBA';


INDEX_NAME |INDEX_TYPE |STATUS
------------------------------|------------|---------------
VIRTUAL_PRUEBA |NORMAL |VALID

Por último, quería mostrar algunas tareas que podemos hacer o no con los índices virtuales:

1- Alterarlos

SQL> alter index VIRTUAL_PRUEBA rebuild;

ERROR at line 1:
ORA-08114: can not alter a fake index

SQL> alter index VIRTUAL_PRUEBA storage(pctincrease 0);

ERROR at line 1:
ORA-08114: can not alter a fake index

2- Intentar transformarlos en índices reales

SQL> create index VIRTUAL_PRUEBA on table_name(col1);

ERROR at line 1:
ORA-00955: name is already used by an existing object

Esto ocurre dado que los índices virtuales generan entradas en algunas tablas del diccionario de datos.
La solución en estos casos es eliminar el índice virtual, y crear el físico

SQL> drop index VIRTUAL_PRUEBA;

Index dropped.

SQL> create index VIRTUAL_PRUEBA on am301(col1);

Index created.

Siguiendo con el tema, lo que si podemos hacer es crear un índice virtual afectando a ciertas columnas de una tabla y por otro lado crear un índice físico (con otro nombre) pero que también afecte a las mismas columnas.

SQL> create index VIRTUAL on emp(col1, col2, col3) nosegment;

Index created.

SQL> create index FISICO on emp(col1, col2, col3);

Index created.

Una vez que terminaron de trabajar con estos índices se recomienda eliminarlos.

Espero que les haya servido.

Saludos!
Gondalf

martes, 9 de marzo de 2010

Borrando una base de datos

Antes que nada, veamos un poco en qué consiste eliminar una base de datos.

Lo que debemos tener en cuenta para eliminar una base de datos los archivos que debemos borrar son:
- datafiles
- redo logs files
- control files
- archivos de parametría

Con la sentencia “drop database” (eso es posible desde la versión 10g de Oracle) eliminamos todos los ‘control files’ y todos los demás archivos listados en dicho archivo.

Ahora bien, para poder ejecutar un “drop database” debemos tener en cuenta lo siguiente:

- La base de datos debe estar cerrada y montada
- La base de datos debe estar montada en modo ‘exclusivo’
- La base de datos debe estar montada en forma ‘restricted’

Para eso, realizamos lo siguiente:

1. Bajamos la base de datos
SQL> shutdown immediate;

2. Montamos la base en modo exclusivo y ‘restricted’
SQL> startup mount exclusive restrict;

3. Por último procedemos a eliminar la base
SQL> drop database;

Cabe aclarar que ‘drop database ’ no elimina los ‘archive logs’ y tampoco tiene efecto sobre copias o backups de la base de datos. Lo mejor para eliminar esos archivos es usar RMAN.

Por último, y quizá la forma más fácil de llevar a cabo el borrado de la base es utilizando ‘Database Configuration Assistant’, con el que podemos eliminar la base y remover los archivos.

Espero les haya servido.

Saludos!
Gondalf.

viernes, 5 de marzo de 2010

FROMUSER TOUSER en DataPump

Para poder usar DataPump debemos crear un “directory object” y otorgar los privilegios necesarios al usuario para que pueda trabajar con ese directorio.
Para crear dicho directorio debemos ejecutar:

SQL> CREATE DIRECTORY prueba_dpump AS ‘/u01/oracle/prueba’;

Una vez creado el directorio, tendremos que darles los permisos necesarios a los usuarios que queramos para que pueda escribir o leer sobre ese directorio. Para eso hacemos lo siguiente (Usamos al usuario Scott como ejemplo):

SQL> GRANT READ,WRITE ON DIRECTORY prueba_dpump TO scott;

A su vez, a nivel operativo oracle debe tener acceso de lectura y escritura sobre el directorio físico.

Una vez que tenemos todo lo anterior, podemos proceder a exportar el owner scott con el siguiente comando:

$ORACLE_HOME\bin\expdp ‘scott/password’ DIRECTORY=prueba_dpump dumpfile=scott.dmp

Habiendo realizado esta pequeña introducción para dataPump lo que quería compartir en este post es el cambio que hubo con dataPump cuando intentamos realizar un import en un owner distinto al que exportamos.

Antes, para realizar esta operación utilizábamos el siguiente comando (en este caso pasaremos las tablas del usuario scott al usuario peter):

$ORACLE_HOME\bin\imp ‘username/password’ FILE=scott.dmp FROMUSER=scott TOUSER=peter TABLES=(*)

Con data Pump Import ahora tenemos:

$ORACLE_HOME\bin\impdp ‘username/password’ DIRECTORY=prueba_dpump DUMPFILE=scott.dmp TABLES=scott.emp REMAP_SCHEMA=scott:jim

Como podemos ver la opción FROMUSER/TOUSER fue sustituida por la opción REMAP_SCHEMA

Espero les haya servido

Saludos!
Gondalf