lunes, 14 de enero de 2013

Utilización de Oracle Java Procedures

Introducción

A partir de la versión Oracle Database 8i se tiene implementado una maquina virtual de Java como parte de los componentes internos de la base de datos. Los Java Procedures son librerías en Java registradas en la base de datos que se caracterizan por el buen desempeño que tienen sobre operaciones lógicas y matemáticas obteniendo mejor tiempo de respuesta versus el lenguaje PL/SQL en este aspecto. Dichas librerías Java se ejecutan en la máquina virtual Java de la base de datos.

La máquina virtual de Java instalada dentro de la base de datos tiene algunos limitantes versus el Java instalado en los sistemas operativos convencionales; algunos de estos son: ausencia de la librería Abstract Window Toolkit (AWT) y Swing para crear componentes gráficos; así mismo no está disponible actualizaciones del componente Java de la base de datos por separado. La versión Oracle Database 10g incluye la versión de Java 1.42 y la versión Oracle Database 11g incluye la versión de Java 1.5.

Oracle Database puede almacenar Java Source & Java Class y podría exponerlo como procedimientos, funciones o triggers de PL/SQL a las aplicaciones.

Este feature no está disponible en la edición XE.

 
Implementación

Es importante conocer que el componente de Java Virtual Machine instalado en la base de datos trabaja bajo un esquema de seguridad conocido como Java2 Security.

Desde Oracle Database 8i están disponible 2 tipos de roles para manejar la seguridad de las aplicaciones Java: JAVAUSERPRIV y JAVASYSPRIV (lleva todos los permisos Java disponibles en la base de datos). Oracle recomienda que evitemos el uso de estos roles y que mejor asignemos los permisos que necesitemos puntualmente. Los permisos que vamos asignando se guardan internamente en objetos llamados Permission los cuales son almacenados en las tablas: PolicyTable y PolicyTablePermission respectivamente.

Si requerimos de algunos permisos para que nuestros programas Java puedan trabajar de manera correcta lo hacemos a través del paquete DBMS_JAVA.

Los permisos más conocidos son java.io.FilePermission y el java.net.SocketPermission.

Java.io.FilePermission permite que nuestro código Java pueda realizar operaciones sobre archivos del sistema operativo. Por default está restringido.

SQL> execute DBMS_JAVA.grant_permission('','java.io.FilePermission','|*','read,write,execute,delete');

Ejemplo:
SQL> execute DBMS_JAVA.grant_permission('SCOTT','java.io.FilePermission','*','read ,write');

Java.net.SocketPermission, permite que nuestro programa pueda enviar tramas vía TCP/IP mediante sockets. Por default también está restringido.

SQL> execute dbms_java.grant_permission('','SYS:java.net.SocketPermission',','connect,resolve,accept,listen');

Ejemplo:
SQL> execute dbms_java.grant_permission('SCOTT','SYS:java.net.SocketPermission','localhost:7000','connect,resolve,accept,listen');

Si deseamos otorgar permisos puntuales a un usuario para algunas operaciones restringidas en la base de datos debemos contamos con el rol JAVA_ADMIN.

Antes de realizar alguna implementación de Java Procedure primero debemos tener correctamente instalado la máquina virtual Java en nuestra base de datos.

SQL> select COMP_NAME,VERSION,STATUS from dba_registry where upper(comp_name) like '%JAVA%';




A continuación se presenta el desarrollo de cuatro diferentes ejemplos de cómo implementar un Java Procedure.


Ejemplo 1:

Realizaremos una función en Java que permita mostrar la fecha que se encuentra en el servidor de base de datos.

a) Creamos el archivo Fecha.java con el siguiente contenido:
public class Fecha {
 public static java.sql.Date getFecha(){
        return new java.sql.Date(new java.util.Date().getTime());
 }
}

Opcional: Podemos compilar el programa en el sistema operativo:
java -c Fecha.java
Se creará el archivo: Fecha.class como producto de la compilación.

b) Registro del programa Java en la base de datos:

loadjava -user usuario/password archivo.java|class|jar

Podemos cargar directamente la fuente del programa (*.java) o el código compilado (*.class). Si cargamos el código fuente no es necesario cargar el código compilado.

Si lo ejecutamos nuevamente el comando loadjava reemplazará la librería anterior por la nueva que estemos cargando.

Nota 1:Si deseamos eliminar la librería cargada ejecutamos:
dropjava -user usuario/password archivo.java|class|jar

Nota 2: Si deseamos validar el registro de los programas Java en la base de datos consultamos el siguiente query.

SQL> select owner,object_name, object_type from dba_objects;

La información de las librerías de Java creadas y cargadas dentro de la base de datos se lleva almacenada en tablas internas creadas por Oracle en cada esquema, una de estas son: JAVA$OPTION y CREATE$JAVA$LOB$TABLE.

Nota 3: Las librerías Java almacenadas en la base de datos se les conoce con el término LIBUNITS, el cual es como un análogo al término DLL en lenguaje C.

c) Publicación.
La publicación se puede realizar a través de Stored Procedures, Funciones o Triggers.

create or replace function Fecha return Date
IS LANGUAGE JAVA NAME 'Fecha.getFecha() return java.sql.Date';
/

Nota: La equivalencia del campo DATE de base de datos es la clase java.sql.Date en Java.

Utilizamos la función:
SQL> select Fecha from dual;


Ejemplo 2:

Crearemos una función en Java que consulte la fecha de la base de datos en un formato determinado y lo devuelva como un varchar.

a) Creamos el archivo BD.java con el siguiente contenido:
import java.sql.*;
import java.util.*;

public class BD
{

 public static String getFecha()
 {
  Connection cn = null;
  PreparedStatement stmt = null;
  String fecha=null;
  try
  {
   Properties prop = new Properties();
   prop.setProperty("user","sys");
   prop.setProperty("password","oracle");
   prop.setProperty("internal_logon","sysdba");
   Class.forName("oracle.jdbc.OracleDriver");
   cn=DriverManager.getConnection("jdbc:oracle:thin:@"+"127.0.0.1:1521/PRD",prop);
   stmt=cn.prepareStatement("select to_char(sysdate,'DD-MM-YYYY') as fecha_BD from dual");
   ResultSet rs=stmt.executeQuery();
   rs.next();
   fecha=rs.getString("fecha_BD");
   rs.close();
   stmt.close();
  }
  catch(Exception e){
   System.out.println(e.getMessage());
  }
  finally{
   if (cn!=null){
    stmt=null;
    cn=null;
   }
  }
  return fecha;
 }

}

b) Registro del programa Java en la base de datos:
loadjava -user friccio/oracle BD.java

c) Publicación
create or replace function FechaBD return varchar
IS LANGUAGE JAVA NAME 'BD.getFecha() return String';
/

Utilizamos la función:
select FechaBD from dual;

Ejemplo 3:

Crearemos un procedimiento en Java que almacene el contenido de un BLOB en un archivo del sistema operativo.

a) Creamos el archivo Java_BLOB.java con el siguiente contenido:
CREATE OR REPLACE JAVA SOURCE NAMED "Java_BLOB" AS

 import java.lang.*;
 import java.sql.*;
 import oracle.sql.*;
 import java.io.*;

 public class Java_BLOB
 {

  public static void crearArchivoBinario(String parchivo, BLOB pBlob) throws Exception
  {
   //Crea un archivo en una ruta específica.
   File archivo = new File(parchivo);
   FileOutputStream outStream = new FileOutputStream(archivo);
   //Conseguimos el contenido binario.
   InputStream inStream = pBlob.getBinaryStream();
 
   //Obtenemos un arreglo de bytes que más adelante llevara el contenido del BLOB.
   int size = pBlob.getBufferSize();
   byte[] buffer = new byte[size];
   int length = -1;
   //Leyendo la información y escribiéndolo en el archivo.
   while ((length = inStream.read(buffer)) != -1)
   {
    outStream.write(buffer, 0, length);
    outStream.flush();
   }
   inStream.close();
   outStream.close();
  }
 
 };
/

Nota 1: En esta ocasión se ha utilizado la sintaxis: CREATE OR REPLACE JAVA SOURCE NAMED, el cual ya realiza los pasos de compilación y publicación de la librería.

Nota 2: Si deseamos compilar de manera específica y ver sus errores ejecutamos los siguientes pasos:

SQL> ALTER java source "" compile;
SQL> show errors java source ""

Ejemplo:


b) Permisos:
Debido a que la aplicación Java escribirá en un directorio del sistema operativo necesitamos garantizar el permiso a la máquina virtual Java a un usuario específico de la base de datos a dicha acción.

SQL> grant JAVASYSPRIV to FRICCIO;
SQL> execute dbms_java.grant_permission('FRICCIO','java.io.FilePermission','*','read ,write, execute, delete');

Al usuario le asignamos el rol JAVASYSPRIV porque esperamos que el usuario pueda ejecutar operaciones sobre cualquier directorio del sistema operativo siempre y cuando el usuario tenga permisos en el mismo a nivel de plataforma.

c) Publicación:
create or replace procedure SPU_Java_BLOB (parchivo varchar, pblob blob)
IS LANGUAGE JAVA NAME 'Java_BLOB.crearArchivoBinario(java.lang.String, oracle.sql.BLOB)';
/

Utilizamos la función:

set serveroutput on
call dbms_java.set_output(2000);
declare
 v_blob blob;
 photo BLOB default EMPTY_BLOB() ;
 v_raw raw(123);
 v_totalBytes number ;
begin
 /*El valor a ingresar se encuentra en formato Hexadecimal,
 teniendo su representacion en ASCII como @*/
 v_raw:='40'; 
 v_totalBytes:=UTL_RAW.length(v_raw);
 /*Se crea un BLOB temporal*/
 dbms_lob.createtemporary(v_blob,TRUE);
 /*Se escribe informacion en el BLOB temporal*/
 DBMS_LOB.WRITE(v_blob,v_totalBytes,1,v_raw);
 /*Se escribe el contenido del BLOB temporal a disco*/
 SPU_Java_BLOB('/tmp/binario.txt',v_blob);
end;
/


Ejemplo 4:

En este ejemplo se creará una función en Java que permita ejecutar un comando en el Sistema Operativo y dicha función esté disponible desde PL/SQL.

a) Creamos el archivo OS.java con el siguiente contenido:
import java.io.*;

public class OS
{

 public static String cmd(String pcomando){
  String output = "";
  String[] programa = null;
  String s="";
  if (System.getProperty("os.name").toLowerCase().indexOf("windows")==-1)
  {
   programa = new String[3];
   programa[0]="/bin/sh";
   programa[1]="-c";
   programa[2]=pcomando;
  }
  else
  {
   programa = new String[4];
   programa[0]="c:\\windows\\system32\\cmd.exe";
   programa[1]="/y";
   programa[2]="/c";
   programa[3]=pcomando;
  }
  Runtime objRt=Runtime.getRuntime();
  try{
   Process objProceso = objRt.exec(programa);
   BufferedReader stdInput = new BufferedReader(new InputStreamReader(objProceso.getInputStream()));
   while ((s = stdInput.readLine()) != null) {
    output = output + s;
    System.out.println(output);
   }
   objProceso.waitFor();
  }
  catch(Exception e){
   System.out.println(e.getMessage());
  }
  return output;
 }

}

b) Registro del programa Java en la base de datos:
loadjava -user friccio/oracle OS.class

c) Publicación:
set serveroutput on
call dbms_java.set_output(2000);
declare
 v_programa varchar(255);
begin
 v_programa:=OS_BD('/bin/touch /tmp/reporte.txt');
 dbms_output.put_line(v_programa);
end;
/

Nota 1: Es importante conocer que si realizamos un export (exp) de esquema o full solo estaríamos llevando las clases java mientras los permisos Java deben ser obtenidos aparte mediante un script. El resultado del script y del export serán las dos fuentes para iniciar una restauración. El export datapump incluye ambas fuentes.

Nota 2: My Oracle Support (MOS) Nota: 183825.1 (How to Backup and Restore Java Classes and Privileges only), cuenta con un script que nos permite obtener todos los permisos registrados en la base datos. El script se presenta a continuación:


spool setjvmprivs.sql
set echo off
set feedback off
set heading off
set linesize 80
set pagesize 1000
column stmt format a70 word_wrapped
select 'exec '||stmt
from (select seq, 'dbms_java.grant_permission('''||grantee||''','''||
             type_schema||':'||type_name||''','''||name||''','''||action||
             ''');' stmt
      from dba_java_policy
      where grantee not in ('JAVADEBUGPRIV', 'JAVASYSPRIV', 'JAVAUSERPRIV',
                         'JAVA_ADMIN', 'JAVA_DEPLOY', 'SYS', 'PUBLIC') and
            type_name!='oracle.aurora.rdbms.security.PolicyTablePermission'
      union all
      select seq,'dbms_java.grant_policy_permission('''||a.grantee||''','''||
             u.name||''','''||permition||''','''||action||''');' stmt
      from sys.user$ u,
           (select seq, grantee,
                   to_number(substr(name,1,instr(name,':')-1)) userid,
                   substr(name,instr(name,':')+1,instr(name,'#') -
                          instr(name,':')-1) permition,
                   substr(name,instr(name,'#')+1 ) action
            from dba_java_policy
            where grantee not in ('JAVADEBUGPRIV', 'JAVASYSPRIV',
                                  'JAVAUSERPRIV', 'JAVA_ADMIN', 'JAVA_DEPLOY',
                                  'SYS', 'PUBLIC') and
                  type_name =
                      'oracle.aurora.rdbms.security.PolicyTablePermission') a
      where u.user#=userid) order by seq;
column stmt clear
set pagesize 24
set heading on
spool off


Nota 3: También si deseamos consultar las clases Java que tenemos registrado en la base de datos consultamos la vista DBA_JAVA_CLASSES.

Nota 4: JVM JIT es un compilador diseñado para la máquina virtual Java el cual transparentemente selecciona procedimientos Java para compilarlos en código nativo, en ventaja de conseguir mejores tiempos de respuesta. Este compilador está disponible a partir de la versión Oracle Database 11gR1.

Conclusión

Oracle Database 8i y las siguientes versiones nos dan la posibilidad de escribir ciertas rutinas en lenguaje Java aprovechando al máximo las dificultades que podríamos tener en el lenguaje PL/SQL al ser Java un lenguaje de programación más completo.

Sobre la seguridad, Oracle nos entrega un completo control sobre los permisos que puede ejecutar cada usuario sobre las librerías de Java registrada.

Debemos ser conscientes que si bien las librerías Java tienen mejor performance en la resolución de cálculos matemático y lógicos, en ningún momento sustituye al lenguaje PL/SQL, ya que dicho lenguaje provee mejor tiempo en la manipulación de la información dentro de la base de datos.


Publicado por Ing. Francisco Riccio. Es un IT Specialist en productos Oracle e instructor de cursos oficiales de certificación Oracle. Está reconocido por Oracle como un Oracle ACE y certificado en productos de Oracle Application & Base de Datos.

e-mail: francisco@friccio.com
web: www.friccio.com

miércoles, 9 de enero de 2013

Result Cache en Oracle Database 11gR2

Introducción

A partir de la versión Oracle Database 11g se cuenta con un espacio de memoria RAM llamado Result Cache que se encuentra alojado dentro del pool Shared Pool con la finalidad de almacenar resultados de queries y funciones PL/SQL que se ejecuten en el servidor de base de datos.


Este nuevo sub pool es muy útil para almacenar resultados de aquellos queries que analizan grandes cantidades de filas y retornan pocas filas; también para funciones PL/SQL que son frecuentemente utilizadas y cuyo resultado depende de información que no cambia mucho en el tiempo.


Implementación


Configuración del Result Cache


Por default el Result Cache almacena una cantidad de memoria RAM por default acorde a la siguiente regla:


a) Si está configurado la base datos con el parámetro MEMORY_TARGET, el Result Cache será  configurado con el 0.25% del valor del parámetro MEMORY TARGET automáticamente.


b) Si está configurado la base de datos con el parámetro SGA_TARGET, el Result Cache será configurado con el 0.5% del valor del parámetro SGA_TARGET automáticamente.


c) Si está configurado el parámetro SHARED_POOL_SIZE, el Result Cache será configurado con 1% del tamaño del valor del SHARED_POOL_SIZE automáticamente.


Si en caso queramos definir un tamaño al Result Cache de forma predeterminada debemos configurar un valor al parámetro RESULT_CACHE_MAX_SIZE. Si el parámetro es configurado con el valor de 0 se deshabilita el sub pool Result Cache.


Asimismo la cantidad máxima de memoria que se puede albergar como resultado de un query o función PL/SQL se define por el parámetro: RESULT_CACHE_MAX_RESULT, cuyo valor por default es de 5% respecto al tamaño del Result Cache.



Utilización para setencias SQL


Si deseamos que el resultado de un query se almacene dentro del Result Cache debemos utilizar el hint result_cache, ejemplo:


SQL> select /*+ result_cache */ count(*) from producto;


Al colocarle el hint de result_cache hace que el resultado del query se guarde en el Result Cache y una vez almacenado recién se devuelva el resultado al usuario.


Si nosotros ejecutamos el query por segunda vez, veremos en el plan de ejecución del query, que el resultado es obtenido del Result Cache haciendo que no sea nuevamente calculado:




Toda operación DML (insert/delete/update) ó DDL (alter table) sobre tablas que influye sobre los resultados almacenados en el Result Cache ocasiona que dichos resultados sean invalidados. En este escenario, el query tendrá que volver a calcular el resultado porque su resultado en el Result Cache fue invalidado.

Asimismo el parámetro RESULT_CACHE_REMOTE_EXPIRATION permite invalidar el resultado de un query que haga llamadas a objetos remotos. Por default tiene el valor de 0, es decir no se almacena resultados que se calculan en base a información de objetos remotos. El valor del parámetro es expresado en segundos.


Si nosotros queremos que el resultado de todo query o función PL/SQL se almacene en el Result Cache sin utilizar el hint result_cache configuramos el parámetro RESULT_CACHE_MODE con el valor de FORCE; por default este parámetro tiene el valor de MANUAL. En caso lo configuremos con el valor de FORCE podemos utilizar el hint no_result_cache si queremos que no se almacene en el Result Cache.


Nota 1: Si deseamos que el Result Cache a pesar de estar configurado sea omitido podemos ejecutar el siguiente procedimiento: DBMS_RESULT_CACHE.BYPASS(true) y colocándole el valor de false volvemos a dejar el Result Cache en modo normal.


Nota 2: No podemos usar Result Cache en sentencias SQL si estas utilizan los siguientes objetos: Tablas temporales, tablas del diccionario de datos, funciones no deterministicas como currval, nextval, sysdate, etc.



Utilización para funciones PL/SQL


Una función PL/SQL debe tener la cláusula RESULT_CACHE si queremos que su resultado se almacene en el Result Cache, ejemplo:




Nota: En la versión Oracle Database 11gR1 se requería la cláusula RESULT_CACHE RELIES ON (), donde la cláusula RESULT_CACHE indica a Oracle Database que invalide el resultado de la función almacenada en el Result Cache para cualquier operación DML o DDL que ocurra sobre la tabla que se liste en el cláusula. En My Oracle Support (MOS) Nota: 1142314.1 (Processes Terminate With ORA-7445 [__intel_new_memcpy()] Errors After Upgrade to 11.2), se especifica que la cláusula RELIES ON ya no debe ser especificada en versiones Oracle Database 11gR2 hacia adelante.

Las restricciones que tiene las funciones PL/SQL sobre Result Cache es que ellas no deben ser funciones pipelined, no pueden tener parámetros out/in out y si son parámetros in no pueden ser de tipo LOB, ref cursor, objetos y colecciones.


Reportes & Validación


a) Si deseamos obtener un reporte del espacio utilizado en el Result Cache podemos utilizar la función: DBMS_RESULT_CACHE.MEMORY_REPORT.




b) La vista V$RESULT_CACHE_STATISTICS permite visualizar cuantos resultados fueron almacenados en el Result Cache y asimismo cuantas veces un query obtuvo sus resultados del cache.




c) Si deseamos ver los queries que tienen resultados guardados en el Result Cache y además de visualizar con que tablas tiene dependencias, estos resultados consultamos la vista: V$RESULT_CACHE_OBJECTS.


d) Para obtener un reporte de cada resultado almacenado en el Result Cache con que objetos de la base de datos tiene dependencia consultamos la vista: V$RESULT_CACHE_DEPENDENCY.

e) Si deseamos limpiar la cache del Result Cache ejecutamos el siguiente procedimiento:

SQL> execute DBMS_RESULT_CACHE.FLUSH;


Result Cache Client


Oracle Database 11g también nos da la posibilidad de utilizar la memoria del lado del cliente para almacenar los resultados de las sentencias SQL que ejecute la aplicación cliente.


Al habilitar el Result Cache Client evitamos viajes innecesarios al servidor de Base de Datos además de ahorrar espacio en él ya que el resultado se almacena en la capa del cliente y no en el caché del servidor. El resultado almacenado en el Result Cache Client es independiente al Result Cache Server, es decir el Result Cache Client puede ser configurado sin que esté configurado el Result Cache en el servidor.


La base de datos es responsable de invalidar un resultado almacenado en el Result Cache Client cuando una operación DML o DDL ha ocurrido sobre un objeto que influye en el resultado de una operación almacenada.


Result Cache Client está habilitado para aplicaciones Oracle OCI, JDBC OCI, ODP.NET, Pro*C, Pro*Cobol y ODBC y no está habilitado por default. El cliente Oracle debe tener una versión mínima a 11gR1 y no está soportado para conexiones beaqueth.


Nota: Subqueries, vistas, objetos remotos, flashback queries, queries que incluyen funciones PL/SQL y queries que referencian políticas VPD en una tabla no son enviados al cache.


Parámetros relacionados a su configuración:


a) CLIENT_RESULT_CACHE_SIZE, determina el máximo tamaño del resultado de un query que un cliente puede almacenar en su cache.


Si su valor es 0 entonces el Result Cache Client está deshabilitado.


b) CLIENT_RESULT_CACHE_LAG, indica el número de segundos que el cliente Oracle validará contra el servidor la consistencia de la información en cache, no es obligatorio su configuración.


Para obtener las métricas del trabajo realizado por el Result Cache Client podemos consultar la vista: CLIENT_RESULT_CACHE_STATS$.


Conclusión


Concluimos que Oracle Database 11g ha diseñado un nuevo sub pool llamado Result Cache que nos ayuda almacenar resultados de nuestros queries y funciones PL/SQL en ventaja de que si son nuevamente invocados dichas operaciones, el trabajo no tenga que ser nuevamente calculado, evitando un gasto innecesario de recursos en la base de datos y por el lado del usuario es una mejora considerable en el tiempo de respuesta.




Publicado por Ing. Francisco Riccio. Es un IT Specialist en productos Oracle e instructor de cursos oficiales de certificación Oracle. Está reconocido por Oracle como un Oracle ACE y certificado en productos de Oracle Application & Base de Datos.

e-mail: francisco@friccio.com

web: www.friccio.com

lunes, 7 de enero de 2013

Oracle Cluster Filesystem (OCFS)


Para este ejemplo particular implementaré una solución de Cluster Filesystem llamada OCFS versión 2.0.

OCFS es una solución de Oracle 100% gratuita para plataformas Linux y Windows.

La implementación será realizada con VMWare Server 1.8 y Oracle Enterprise Linux 4.7.

La utilización de VMWare es netamente educativo, su finalidad en este ejercicio es simular el storage compartido entre dos servidores.

Paso 1.- Configurar adecuadamente los servidores.

a) Ambos servidores deben tener dos tarjetas de red, uno para la conexión de los usuarios al servidor y otra tarjeta para una conexión privada, la cual tiene como finalidad que cada servidor pueda comunicarse con el otro servidor y pueda además asegurarse que el otro servidor vive. Si utilizamos OCFS para implementar Oracle RAC podemos utilizar la misma red privada para la interconnect del clusterware.

En mi ejemplo: El servidor 1 tiene el IP Público (192.68.1.5) e IP Privado (20.0.0.5) y el servidor 2 tiene el IP Público (192.68.1.6) y el IP Privado (20.0.0.6).

b) Ambos servidores deben tener un storage común, es decir ambos servidores deben poder leer y escribir sobre un mismo conjunto de discos al mismo tiempo.

Figura 1

En la implementación de VMWare como muestro en la figura 1, he colocado 2 tarjetas de red y además un disco que será compartido entre ambos servidores, como característica este disco debe tener la propiedad de Independent-persistent y además debe estar configurado en otra tarjeta controladora (Ejemplo: SCSI 1) respecto a los demás discos internos (SCSI 0).

Adicional debo indicar que los discos serán compartidos y esto se realiza en cada archivo de configuración de VMWare (*.vmx) de cada servidor.

Ejemplo:

Colocamos scsi1:0 porque es el disco que estamos compartiendo entre los servidores.



Paso 2.- Particionamiento del disco compartido.

Vemos todas las particiones con el comando: fdisk -l, en nuestro ejemplo vemos que tenemos asignado un nuevo disco "sdg" sin partición.


Lo particionamos (fdisk /dev/sdg), solo es necesario realizarlo en un servidor:



Paso 3.- Instalacion del Software de OCFS.

Debemos descargar OCFS de acuerdo a nuestra versión de kernel de Linux (uname -a) en la siguiente dirección: http://oss.oracle.com/projects/ 

En el caso de Oracle Enterprise Linux los rpm de OCFS se encuentran en la media del producto.Para saber la plataforma con que estamos corriendo podemos ejecutar el siguiente comando: 
rpm -qf /boot/vmlinuz-`uname -r` --queryformat "%{ARCH}\n"

Figura 2
En nuestro escenario iniciaremos la instalación en ambos servidores:




Paso 4.- Formateamos la partición en formato OCFS.


Paso 5.- Creamos el archivo de configuración del OCFS en ambos servidores.


Esto debe ser realizado en ambos servidores.

Paso 6.- Iniciamos la configuración.

Ejecutamos en ambos nodos: /etc/init.d/o2cb configure (Dejamos los valores por default).



Paso 7.- Habilitamos el servicio de OCFS (Nos permite registrar el servicio O2CB).

Ejecutamos en ambos nodos: /etc/init.d/o2cb enable



Paso 8.- Montando los discos.



Probando:

Servidor 1 (Copiando algunos archivos al disco compartido).

Servidor 2 (Revisando los archivos copiados).


Como se puede apreciar ambos servidores pueden leer y escribir en un mismo storage, el cual es la limitante para un filesystem como EXT3 o NTFS. Además nos permite crear un cluster activo / activo.

Con esta implementación podríamos ya empezar la instalación de un cluster de Oracle (Clusterware).

Espero que este artículo pueda complementar lo aprendido en el artículo anterior y le sea útil si están comenzado un proyecto de alta disponibilidad.

Podemos encontrar la información oficial de OCFS en la siguiente página: http://oss.oracle.com/projects/ocfs2/


Publicado por Ing. Francisco Riccio. Es un IT Specialist en productos Oracle e instructor de cursos oficiales de certificación Oracle. Está reconocido por Oracle como un Oracle ACE y certificado en productos de Oracle Application & Base de Datos.

e-mail: francisco@friccio.com
web: www.friccio.com