viernes, 20 de agosto de 2010

Creación de un SQL Tuning Advisor

==================================
= Eliminamos la tarea de tuning
==================================

exec dbms_sqltune.drop_tuning_task('task1');


==================================
= Creamos la tarea de tuning
==================================

DECLARE
tarea_tuning VARCHAR2(30);
sql CLOB;
BEGIN
sql := 'SELECT * from dual';
tarea_tuning := DBMS_SQLTUNE.CREATE_TUNING_TASK(
sql_text => sql,
user_name => USER,
scope => 'COMPREHENSIVE',
time_limit => 60,
task_name => 'task1',
description => 'prueba de tarea de tuning');
END;
/

/* hay un parametro mas de bind_list */


==================================
= Verificamos que la tarea este creada
==================================

SELECT task_name FROM DBA_ADVISOR_LOG WHERE owner = USER;


======================================
= Ejecutamos la tarea
======================================

BEGIN
DBMS_SQLTUNE.EXECUTE_TUNING_TASK( task_name => 'task1' );
END;
/


===================================
= Controlamos el estado de la tarea
===================================

SELECT task_id, status FROM USER_ADVISOR_TASKS WHERE task_name = 'task1';


======================================
= Controlamos el progreso del SQL Tuning Advisor
======================================

SELECT sofar, totalwork
FROM V$ADVISOR_PROGRESS
WHERE task_id = (SELECT task_id FROM USER_ADVISOR_TASKS WHERE task_name = 'task1');


=====================================
= Mostramos el resultado del SQL Tuning Advisor
=====================================

SELECT DBMS_SQLTUNE.REPORT_TUNING_TASK( 'task1') FROM DUAL;

Numero del día

A muchos les habrá pasado que de acuerdo a como se conecten a la base de datos, sea desde una terminal, desde el server, a través de un ODBC cambia la manera en que Oracle les devuelve el numero de día de una fecha en particular.

Esto sucede ya que una terminal puede tomar otro NLS_LANG distinto al del servidor.

A continuación vamos a ver como cambia el numero de día (por lo general se utiliza el domingo o el lunes como 1) de acuerdo al cambio de parámetro en el NLS_LANG


ora1@test ] export NLS_LANG='AMERICAN';
ora1@test ] sqlplus / as sysdba

SQL*Plus: Release 10.2.0.4.0 - Production on Mon Aug 20 10:35:15 2005
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

Connected to:
Oracle9i Enterprise Edition Release 10.2.0.4.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 10.2.0.4.0 - Production

SQL> select to_char(sysdate, 'D') from dual;

T
-
2


ora1@test ] export NLS_LANG='ENGLISH'
ora1@test ] sqlplus / as sysdba

SQL*Plus: Release 10.2.0.4.0 - Production on Mon Aug 20 10:40:43 2010
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

Connected to:
Oracle10g Enterprise Edition Release 10.2.0.4.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 10.2.0.4.0 - Production

SQL> select to_char(sysdate, 'D') from dual;

T
-
1


Espero les haya servido

Saludos!
Gondalf.

jueves, 10 de junio de 2010

Resultado de un query de varias filas concatenadas en una

La idea de este post es acercarles una función que quizás en algún momento les sea de utilidad.

El propósito de la función es concatenar el resultado de un query que devolvió varias filas en solo 1,
la función es la siguiente:

CREATE OR REPLACE FUNCTION concatfilas(qry IN VARCHAR2) RETURN VARCHAR2 IS
filaFinal VARCHAR2(4000);
result VARCHAR2(4000);
cur sys_refcursor;
BEGIN OPEN cur FOR qry;
LOOP
FETCH cur INTO result;
EXIT WHEN cur%NOTFOUND;
IF filaFinal IS NULL THEN
filaFinal := resul;
ELSE
filaFinal := filaFinal ',' result;
END IF;
END LOOP;
RETURN filaFinal;
END;
/

Ejemplo

SQL> create table prueba (nombre varchar2(30));

Table created.

SQL> insert into prueba values(‘Luis’);

1 row created.

SQL> insert into prueba values(‘Bruno’);

1 row created.

SQL> insert into prueba values(‘Matias’);

1 row created.

SQL> insert into prueba values(‘Gonzalo’);

1 row created.

SQL> commit;

1 row created.

SQL> select concatfilas('SELECT nombre FROM prueba') as nombres
2 FROM dual;


NOMBRES
------------------------------------------------------------------
Luis, Bruno, Matias, Gonzalo


Espero les haya servido

Saludos!
Gondalf.

miércoles, 9 de junio de 2010

Perdida de un Control File

Lo que primero tenemos que tener en claro que la pérdida de un control file multiplexado inmediatamente realiza un abort a la instancia. Como nosotros tenemos multiplexado nuestro control file (de no tenerlo, hacerlo!), realizar una recuperación de la instancia no es nada complicado.

Para el siguiente ejemplo supongamos que tenemos 3 control files:
/u02/oradata/test/control01.ctl
/u03/oradata/test/control02.ctl
/u04/oradata/test/control03.ctl

Por un fallo en el /u04 perdemos el control03.ctl, por ende la instancia cae dada esta perdida.
Para poder hacer el recover de la instancia lo que hacemos es modificar el parámetro CONTROL_FILES dentro del SPFILE suprimiendo el control03.ctl.

Los pasos a seguir son:

- Levantamos la base en NOMOUNT, lo hacemos en este modo dado que en MOUNT la base ya realiza un chequeo de los control files.

SQL> startup nomount
ORACLE instance started.
Total System Global Area     188743680 bytes
Fixed Size     778036 bytes
Variable Size     162537676 bytes
Database Buffers     25165824 bytes
Redo Buffers     262144 bytes


- Con la instancia en NOMOUNT podemos modificar el paramentro CONTROL_FILE dentro del spfile:

SQL> alter system set control_files =
2 '/u02/oradata/test/control01.ctl',
3 '/u03/oradata/test/control02.ctl'
4 scope = spfile;

System altered.

- Bajamos la instancia

SQL> shutdown immediate

ORA-01507: database not mounted
ORACLE instance shut down.


- Levantamos la instancia con el nuevo parametro aplicado

SQL> startup
ORACLE instance started.
Total System Global Area       188743680 bytes
Fixed Size       778036 bytes
Variable Size       162537676 bytes
Database Buffers       25165824 bytes
Redo Buffers       262144 bytes
Database mounted.
Database opened.


- Por último lo que podemos hacer es checkear que el parametro haya quedado correcto para lo cual hacemos la siguiente consulta

SQL> select name, value
2 from v$spparameter
3 where name = 'control_files';

NAME VALUE
--------------- --------------------------------------
control_files /u02/oradata/test/control01.ctl
control_files /u03/oradata/test/control02.ctl



Espero les haya servido

Saludos!
Gondalf

domingo, 30 de mayo de 2010

Renombrar un “Log Member”

Para poder renombrar un redo log member lo que necesitamos en primer lugar es el nuevo archivo de redo ya que el comando de SQL lo que hace únicamente es cambiar el puntero interno en el control file hacia el nuevo archivo de redo, es decir que el comando de SQL no modifica el archivo del sistema operativo.

Entonces, para poder renombrar el archivo de redo vamos a realizar los siguientes pasos:

1. Realizamos un shutdown de la base
SQL> shutdown immediate;


2. Copiamos o renombramos el archivo de redo utilizando comandos del sistema operativo


3. Montamos la base de datos

SQL> startup mount;


4. Realizamos el cambio en el puntero del archivo de control.

SQL> ALTER DATABASE RENAME FILE ‘old_redo_file’ TO              ‘new_redo_file’;


5. Abrimos la base de datos

SQL> ALTER DATABASE OPEN;


6. Por último realizamos un backup del archive de control ya que realizamos un cambio en el.


Espero les haya servido

Saludos!
Gondalf

miércoles, 19 de mayo de 2010

Cambiando el orden de las columnas

Como alguno de ustedes ya sabrá el proceso de cambiar el orden las columnas de una tabla en Oracle no se realiza con un simple ALTER TABLE.

Para poder llevar a cabo esta tarea a continuación vamos a ver una sucesión de pasos que nos van a ayudar a solucionar nuestra necesidad.

Cabe aclarar que si la tabla tiene indices asociados primero habría que relevarlos dado que los vamos a perder con este procedimiento.

SQL> create table EJEMPLO (col1 number, col2 number, col3 number);

Table created.

SQL> desc EJEMPLO;
Name          Null?     Type
---------- ------ ----------------
COL1 NUMBER
COL2 NUMBER
COL3 NUMBER

SQL> create table AUXILIAR as select col3, col2, col1 from EJEMPLO;

Table created.

SQL> drop table EJEMPLO;

Table dropped.

SQL> alter table AUXILIAR rename to EJEMPLO;

Table altered.

SQL> desc EJEMPLO;
Name          Null?     Type
---------- ------ ----------------
COL3 NUMBER
COL2 NUMBER
COL1 NUMBER

Espero les haya servido.

Saludos!
Gondalf

lunes, 10 de mayo de 2010

Agregar un disco a un diskgroup en ASM

La idea de este post es mostrarles un poco como podemos agregar espacio (un disco) a nuestro ASM, primero vamos
a crear el link necesario a nuestro raw device para que ASM pueda "verlo", para realizar esto hacemos lo siguiente:

1- Nos paramos en el directorio donde tenemos creados los links a los raw devices

TEST:/u00/oradata/asm# ls -latr
total 2
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_01 -> /dev/rdisk/disk61
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_02 -> /dev/rdisk/disk68
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_03 -> /dev/rdisk/disk73
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_04 -> /dev/rdisk/disk81
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_05 -> /dev/rdisk/disk86
drwxrwxr-x 2 oracle dba 1024 May 15 2009 .
drwxrwxr-x 4 oracle dba 96 May 7 15:22 ..
2- Una vez que el sys admin nos indica que raw tenemos presentado vamos a proceder a darle los permisos necesarios
(en este ejemplo será el disk78)

TEST:/u00/oradata/asm# chown oracle:dba /dev/rdisk/disk78

3- Generamos el link necesario con el comando de UNIX ln -s

TEST:/u00/oradata/asm# ln -s /dev/rdisk/disk78 /u00/oradata/asm/asm_disk_06

4- Revisamos nuestro nuevo link

TEST:/u00/oradata/asm# ll
total 0
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_01 -> /dev/rdisk/disk61
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_02 -> /dev/rdisk/disk68
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_03 -> /dev/rdisk/disk73
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_04 -> /dev/rdisk/disk81
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_05 -> /dev/rdisk/disk86
lrwxr-xr-x 1 root sys 17 May 7 16:12 asm_disk_06 -> /dev/rdisk/disk78
5- Como vemos el link lo creamos con un usuario y un grupo erróneo, por lo que debemos cambiarlo, para eso ejecutamos lo siguiente

TEST:/u00/oradata/asm# chown -h oracle:oinstall asm_disk_06

6- Volvemos a chequear

TEST:/u00/oradata/asm# ll
total 0
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_01 -> /dev/rdisk/disk61
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_02 -> /dev/rdisk/disk68
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_03 -> /dev/rdisk/disk73
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_04 -> /dev/rdisk/disk81
lrwxr-xr-x 1 oracle oinstall 17 May 15 2009 asm_disk_05 -> /dev/rdisk/disk86
lrwxr-xr-x 1 oracle oinstall 17 May 7 16:12 asm_disk_06 -> /dev/rdisk/disk78
7- Por otro lado chequemos que el raw presentado tenga los permisos necesario para que ASM lo pueda acceder correctamente

TEST:/u00/oradata/asm# ls -latr /dev/rdisk/disk78
crw-r-----   1 oracle     dba         23 0x000014 May 15  2009 /dev/rdisk/disk78
/*********************************************/

Una vez terminado el trabajo de generar el link para ASM estamos en condiciones de agregar el disco a nuestro diskgroup.
Quiero aclarar que voy a seguir los pasos que aconseja Oracle para agregar un nuevo disco a un diskgroup existente (Metalink ID 557348.1)

Paso 1 - Creamos un nuevo diskgroup para testear si ASM puede acceder al nuevo disco y asi no correr riesgos con nuestro diskgroup productivo
SQL> CREATE DISKGROUP TEST EXTERNAL REDUNDANCY DISK 'YOUR DISK';

Paso 2 - Checkeamos si el diskgroup esta creado y montado
SQL> SELECT STATE, NAME FROM V$ASM_DISKGROUP;

Paso 3 - Si tenemos varias instancias de ASM (hablamos de un RAC sobre ASM) debemos montar el diskgroup en las demas instancias de ASM
SQL> ALTER DISKGROUP TEST MOUNT;

Paso 4 - Chequeamos en todas las demás instancias de ASM si el diskgroup está montado
SQL> SELECT STATE, NAME FROM V$ASM_DISKGROUP;

Paso 5 - Desmontamos el diskgroup de todas las instancias menos de una, es de esta última de donde eliminamos la instancia de ASM
SQL> alter diskgroup test dismount; --(desde todas las instancias de ASM salvo de una).

SQL> DROP DISKGROUP TEST; --(desde la instancia ASM de donde no desmontamos el diskgroup).

Paso 6 - Agregamos el nuevo disco a nuestro diskgroup existente
SQL> ALTER DISKGROUP ADD DISK 'YOUR DISK';

Espero les haya servido.

Saludos!
Gondalf