SafeChildren Banner

Havoc Oracle Solaris Experts

lunes, 15 de febrero de 2010

DBLinks en PostgreSQL

Introducción
Para aquellos que ya saben Qué es un DBLink pueden pasar al siguiente apartado. Para aquellos que no saben qué es, lo resumiremos como Un sistema que nos permite acceder de una base de datos a otra de forma transparente.

La idea es poder acceder desde la base de datos DB1 a los objetos de la base de datos DB2 de forma sencilla y transparente, pudiendo utilizar los comando SQL generales.

En Oracle haremos esto utilizando el símbolo "@" para hacer referencia a que la SQL pertenece a un base de datos remota.
 SQL> SELECT 1 FROM DUAL@OLTP2;

         1
----------
         1
En postgres es un poco diferente, principalmente porque el soporte para dblinks no está activado por defecto y debemos cargar el archivo dblink.sql que se encuentra en $POSTGRES_HOME/share/contrib/dblink.sql

Un ejemplo Completo
Vamos a crear dos base de datos -Test1 y Test2- y una tabla en cada una de ellas, con un registro de "Saludos desde Test1" -para Test1- y "Saludos desde Test2" -para Test2-. Posteriormente, haremos una consulta desde Test2 a la tabla de Test1 a traves de un dblink.
$ psql -U postgres
psql (8.4.0)
Digite ?help? para obtener ayuda.

postgres=# create database test;
CREATE DATABASE
postgres=# create database test2;
CREATE DATABASE
postgres=# \c test1
psql (8.4.0)
Ahora está conectado a la base de datos "test1".
test1=# create table test1(nombre character varying);
CREATE TABLE
test1=# insert into test1 values('saludos desde test1');
INSERT 0 1
test1=# \c test2
psql (8.4.0)
Ahora está conectado a la base de datos "test2".
test2=# create table test2(nombre character varying);
CREATE TABLE
test2=# insert into test2 values ('saludos desde test2');
INSERT 0 1
Una vez creada la estructura, vamos a cargar el soporte de dblink en la base de datos TEST2
$ psql -U postgres test2 -f $POSTGRES_HOME/share/contrib/dblink.sql
Una vez cargado, nos conectaremos a TEST2 y haremos la prueba de conexión -en nuestro caso no es necesario poner una contraseña, sin embargo, si es vuestro caso, simplemente deberemos incluir la cadena password=CONTRASEÑA en la conexión-
$ psql -U postgres test2
psql (8.4.0)
Digite ?help? para obtener ayuda.

test2=# select dblink_connect('dbname=test1');
 dblink_connect
----------------
 OK
(1 fila)

test2=# \q
Ya hemos dicho antes que en PostgreSQL es un poco diferente de Oracle, y uno de los cambios es que debemos informar a PostgreSQL de qué tipos son los resultados devueltos ya que sino -postgres- no será capáz de entender las cláusulas WHERE de la consulta SQL.

Por lo tanto, la recomendación -por parte de PostgreSQL- es crear una vista que sea la que realmente llame al DBLink y nosotros acceder a dicha vista de forma normal. El formato de la instrucción será el siguiente:
 SELECT *
        FROM dblink('dbname=NOMBREDB password=PASSWORD', 'SQL_A_EJECUTAR')
        AS t1(NOBRE_COLUMNA1 TIPO COLUMNA1, NOMBRE_COLUMNA2 TIPO_COLUMNA2, ...);
Así, siguiendo con nuestro ejemplo, vamos a crear una vista en la base de datos TEST2 que nos permitirá acceder a los datos de TEST1

test2=# select * from test2;
       nombre       
---------------------
 saludos desde test2
(1 fila)

test2=#  CREATE OR REPLACE VIEW test_view AS
test2-#       SELECT nombre
test2-#         FROM dblink('dbname=test1', 'select nombre from test1')
test2-#         as t1(nombre character varying);
CREATE VIEW
test2=# select * from test_view;
       nombre       
---------------------
 saludos desde test1
(1 fila)
Conclusión
El acceso a diferentes base de datos es un de las opciones más interesantes que podemos encontrar en el mundo SQL y PostgreSQL nos ofrece un sistema -aunque un poco extraño al principio- muy potente y flexible.

Referencias

viernes, 12 de febrero de 2010

Cómo Registrar los Accesos de SSH en Solaris

Introducción
En Solaris, por defecto, los registros de intentos de acceso mediante SSH no quedan registrados. Para poder registrarlos debemos modificar el valor de la variable de configuración <auth.notice> de <syslog>.

Para ello, editaremos el archivo de configuración /etc/syslog.conf y descomentaremos la entrada <auth.notice>
# vi /etc/syslog.conf
    auth.notice                    ifdef(`LOGHOST', /var/log/authlog, @loghost)
    # si queremos todos los niveles
   #auth.notice;auth.info;auth.debug                ifdef(`LOGHOST', /var/log/authlog, @loghost)
Una vez modificado, debemos recargar la configuración de nuestro syslogd de la siguiente forma
# pkill -HUP syslogd
Podemos consultar los intentos de accesos en el archivo</var/log/authlog> utilizando -por ejemplo- el comando <tail> o si queremos algo más avanzado LogWatch

Referencias

lunes, 8 de febrero de 2010

Manejo de Project y Configuraciones Dinámicas en Solaris 10 - Parte 1

Introducción
Una de las ventajas que nos ofrece Solaris en la Gestión Dinámica de Recursos -ya hemos hablado en otras ocasiones de esto como en Instalar varias Bases de Datos Oracle en la misma máquina- pero hoy vamos a ver con más detalle Cómo Gestionar Dinámicamente los valores de los Projectos.

Para ello, vamos a utilizar el comando <prctl> que nos va a permitir modificar y comprobar los valores que tenemos asignados por: project, task y pid.

Antes de empezar, debemos tener en cuenta que debemos conocer algunos conceptos básicos del manejo de projects como: Cómo saber cuál es el project actual, Cómo Ejecutar un proceso con un project diferente o Cómo cambiar el project de un proceso

La gestión de los recursos de nuestra máquina utilizando project nos ofrece una granualidad muy alta a la hora de expecificar: Memoria Máxima, Tiempo de CPU, Semáforos, etc. De esta forma, podemos ir ajustando las necesidades de nuestros procesos de forma dinámica.


Creación Project y Modificación Dinámica
Vamos a ver con un ejemplo, cómo podemos crear y modificar los valores de un project <en caliente> y cómo afecta al sistema. Lo primero que haremos será crear el project TEST.MIN con un valor de project.cpu-shares = 30 y luego, lo modificaremos a 100

# projadd -c 'Test Project' -G sysadmin -K 'project.cpu-shares=(privileged,200,none)' test.min
# cat /etc/project |grep test
test.min:102:Test Project::sysadmin:project.cpu-shares=(privileged,200,none)
Una vez creado, vamos a ejecutar nuestras operaciones utilizando este nuevo project -test.min-
# newtask -p test.min
# id -p
uid=0(root) gid=0(root) projid=102(test.min)
Como hemos comentado al principio, para poder modificar los valores de un project con una tarea en ejecución será necesario utilizar el comando <prctl> ya que, si utilizamos el comnado <projmod> estos cambios sólo se verán en las nuevas ejecuciones y no en las actuales. Veamos un ejemplo, para ello, vamos a obtener el valor de cpu-shares y posteriormente lo modificaremos con projmod y veremos cómo no se ha modificado. Por último, utilizaremos prctl para modificar el valor y comprobar cómo ahora si ha sido modificado.
# prctl -n project.cpu-shares -i pid 855
process: 855: prstat -J
NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
project.cpu-shares
        privileged        200       -   none                                 -
# projmod -sK'project.cpu-shares=(privileged,60,none)' test.min
# prctl -n project.cpu-shares -i pid 855
process: 855: prstat -J
NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
project.cpu-shares
        privileged        200       -   none                                 -
# cat /etc/project |grep test
test.min:102:Test Project::sysadmin:project.cpu-shares=(privileged,60,none)
Como podemos ver, el cambio utilizando el comando <projmod> no se ha visto reflejado sobre nuestro proceso <855> ya que está en ejecución.

Ahora, vamos a ver cómo utilizando <prctl> el cambio se ve reflejado en el proceso pero no en el archivo de configuración </etc/projects>
# prctl -r -t privileged -n project.cpu-shares -v 350 -i pid 855
# prctl -n  project.cpu-shares -i pid 855
process: 855: prstat -J
NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
project.cpu-shares
        privileged        350       -   none                                 -
# cat /etc/project |grep test
test.min:102:Test Project::sysadmin:project.cpu-shares=(privileged,60,none)
En el ejemplo hemos modificado los valores para un pid en concreto, pero, la forma más habitual será hacer referencia al project para ello, deberemos utilizar el siguiente comando
#  prctl -r -t privileged -n project.cpu-shares -v 200 -i project test.min


Conclusiones
Podemos ver cómo con el uso de project y el comando prctl vamos a ajustar las necesidades de nuestro sistema de forma sencilla y rápida. Si a esto unimos el uso de pset y pools podemos tener un ajuste muy fino de los recursos asignados a cada proceso -project-

Os animo a investigar las opciones de prctl desde su man page y así poder explorar todas las opciones que nos aporta.

Referencias

miércoles, 3 de febrero de 2010

Gestión y Husos Horarios en Oracle

Introducción
El manejo de fechas es una de las tareas más tediosas que existen en cualquier sistema, y por supuesto, Oracle no será una excepción. Vamos a ver cómo podemos utilizar las herramientas de TimeZone <desplazamiento horario> que nos proporcionan.

Por defecto -y a no ser que cambiemos esta de forma consciente- Oracle define el desplazamiento de la base de datos como GMT+0, es decir, no se encuentra desplazada. De esta forma, es capáz de obtener las diferentes representaciones de las fechas en función de su desplazamiento.

Vamos a ver cómo podemos saber si tenemos configurada nuestra base de datos y cuál es su <dbtimezone>

SQL> SELECT dbtimezone FROM DUAL;

DBTIME
------
+00:00
Ahora bien, nuestro TimeZone estará formado por Continente/Ciudad -en la mayoría de los casos- y en el nuestro será <Europe/Madrid>, pero podemos obtener una lista de todos los TimeZone que Oracle conoce haciendo la siguiente consulta
SQL> SELECT DISTINCT tzname FROM V$TIMEZONE_NAMES ORDER BY 1;

TZNAME
----------------------------------------------------------------
Africa/Algiers
Africa/Cairo
Africa/Casablanca
Africa/Ceuta
Africa/Djibouti
Africa/Freetown
Africa/Johannesburg
Africa/Khartoum
Africa/Mogadishu
Africa/Nairobi
Africa/Nouakchott
...
... continúa ...
...
Bien, una vez introducido los principales elementos en el uso de husos horarios, vamos a ver cómo operar con ellos. Lo primero que haremos será obtener la fecha-hora del sistema

SQL> SELECT CURRENT_TIMESTAMP FROM DUAL;

CURRENT_TIMESTAMP
---------------------------------------------------------------------------
01/02/10 14:28:02,990759 +01:00

Ahora, vamos a ver esta hora como es representada en Arizona, es decir, qué hora es allí. Para ello, vamos a utilizar una función <TZ_OFFSET> que nos dará el desplazamiento horario respecto a nuestra base de datos -recordar que es GMT+0-

SQL> SELECT TZ_OFFSET('US/Arizona') FROM DUAL;

TZ_OFFS
-------
-07:00

Muchos podéis pensar que resto TZ_OFFSET a la hora y ya tengo la hora desplazada, ..., ummm, pues la verdad es que no. Más adelante veremos en qué circustancias eso no nos sirve.

Así que, la solución es utilizar la función <FROM_TZ> que nos permite convertir una Hora a un desplazamiento en concreto.

Continuando con el ejemplo, queremos saber la hora en US/Arizona
SQL> SELECT
  2  FROM_TZ( CAST(CURRENT_TIMESTAMP AS TIMESTAMP), 'Europe/Madrid') 
  3  AT TIME ZONE 'US/Arizona'AS Hora_Arizona
  4  FROM DUAL;

HORA_ARIZONA
---------------------------------------------------------------------------
01/02/10 06:38:39,705886 US/ARIZONA
También podemos hacer las variantes que queramos, por ejemplo, representar una Fecha-Hora de US/Arizona en nuestro desplazamiento Europe/Madrid

SQL> SELECT
  2  FROM_TZ(CAST(TO_DATE('1980-12-31 23:59:59','YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP),'US/Arizona')
  3  AT TIME ZONE 'Europe/Madrid' AS Hora_Madrid
  4  FROM DUAL;

HORA_MADRID
---------------------------------------------------------------------------
01/01/81 07:59:59,000000 EUROPE/MADRID
Un poco más complejo
Como todos los años, volveremos a tener dos cambios de hora: Horario de Verano y Horario de Invierno. Bien, es aquí donde tendremos los problemas y por qué no podemos restar el valor de TZ_OFFSET a nuestra hora -principalmente porque tenemos que comprobar en que día estamos-. El 28 de Marzo a las 02:00h serán las 03:00h -en España- y por lo tanto habrá un período de tiempo en el cual, el desplazamiento no se corresponderá con el TZ_OFFSET -hasta que no se hagan los ajustes en aquellos países que realizan el cambio- pero, además, si es un país donde no se hacen cambios tendremos un TZ_OFFSET diferente para verano y otro para invierno.

Todos estos cálculos los realiza Oracle por nosotros, así que, vamos a utilizarlos. Veamos el ejemplo del 28 de Marzo con un desplazamiento de Africa/Mogadishu

SQL> SELECT TZ_OFFSET('Africa/Mogadishu') FROM DUAL;

TZ_OFFS
-------
+03:00

SQL> SELECT
1    FROM_TZ(CAST(TO_DATE('2010-03-28 01:00:00','YYYY-MM-DD
2    HH24:MI:SS') AS TIMESTAMP),'Europe/Madrid')
3    AT TIME ZONE 'Africa/Mogadishu' AS Hora_Mogadishu
4    FROM DUAL;


HORA_MOGADISHU
---------------------------------------------------------------------------
28/03/10 03:00:00,000000 AFRICA/MOGADISHU

SQL> SELECT
1    FROM_TZ(CAST(TO_DATE('2010-03-28 03:00:00','YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP),'Europe/Madrid')
2    AT TIME ZONE 'Africa/Mogadishu' AS Hora_Mogadishu
3    FROM DUAL;

HORA_MOGADISHU
---------------------------------------------------------------------------
28/03/10 04:00:00,000000 AFRICA/MOGADISHU
Como vemos en el ejemplo, el desplazamiento para Africa/Mogadishu es GMT+3, por lo tanto, si España es GMT+1, cabe pensar que añadiendo 2 horas se puede obtener la hora. Sin embargo, si nos fijamos con más detalle en la segunda SQL -cuando la hora es las 03:00h- en Mogadishu son las 04:00h y no las 05:00h. Esto se debe a que en España se ha cambiado de horario y en Mogadishu no se realiza ese cambio.

Además, según este esquema la en España la franja horaria 02:01:00h a 02:59:59h no existe -ya que a las 02:00h son las 03:00h- y si intentamos hacer cualquier cambio horario en esta franja, Oracle mostrará el siguiente error:

SQL> SELECT
  2  FROM_TZ(CAST(TO_DATE('2010-03-28 02:10:00','YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP),'Europe/Madrid')
  3  AT TIME ZONE 'Africa/Mogadishu' AS Hora_Mogadishu
  4  FROM DUAL;
FROM_TZ(CAST(TO_DATE('2010-03-28 02:10:00','YYYY-MM-DD HH24:MI:SS') AS TIMESTAMP),'Europe/Madrid')
        *
ERROR at line 2:
ORA-01878: specified field not found in datetime or interval
Conclusiones
Realmente el manejo de Fechas y Horas en diferentes husos y desplazamientos horarios puede darnos muchos problemas. Por ello, es de vital importancia utilizar las funciones que nos proporciona Oracle y sobre todo, tener el sistema con los últimos parches de TZ disponibles.

Referencias

lunes, 1 de febrero de 2010

Desbloquear Cuenta Usuario Oracle

Introducción
Si tenemos activada la opción de bloqueo de cuentas en Oracle después de un número de intentos fallidos, al intentar conectarnos Oracle nos devolverá el error <ORA-28000 - Cuenta Bloqueada>. Para poder desbloquearla simplemente debremos utilizar la instrucción <ALTER USER> con la opción <ACCOUNT UNLOCK>

Veamos un ejemplo, primero bloquearemos la cuenta TEST y luego la desbloquearemos
$ sqlplus / as sysdba

SQL*Plus: Release 10.2.0.4.0 - Production on Wed Jan 27 17:22:08 2010

Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.

Conectado a:
Oracle Database 10g Release 10.2.0.4.0 - 64bit Production

SQL>  ALTER USER TEST ACCOUNT LOCK;

Usuario modificado.

SQL> CONN TEST
Introduzca la contraseña:

ERROR: ORA-28000: la cuenta esta bloqueada
Advertencia: !Ya no esta conectado a ORACLE!

SQL> CONN / AS SYSDBA

SQL> ALTER USER TEST ACCOUNT UNLOCK;

Usuario modificado.

SQL> CONN TEST
Introduzca la contraseña:

Conectado.

SQL> QUIT

Referencias