martes, 11 de octubre de 2016

OTN Appreciation Day: Oracle read/write consistency #ThanksOTN

Me sumo a la iniciativa de Tim Hall de publicar hoy un post corto explicando porque nos gusta una funcionalidad de Oracle.

De las miles de funcionalidades que tiene la base de datos Oracle quiero resaltar una central - la versión 4 de Oracle (año 1984) implementó Read Consistency, un mecanismo de consistencia de datos usando Multiversion Concurrency Control (MVCC) que permite sesiones concurrentes de lectura sobre datos que están siendo modificados por otra sesión.
Esto es la I de las propiedades ACID que cumplen las bases de datos transaccionales.

MVCC es algo normal en las bases de datos modernas (por ejemplo en MySQL y Postgres) pero fue muy innovador para su época.

Lo que me parece más importante es que tiene un impacto directo sobre la capacidad de respuesta y escalabilidad de la base de datos, ya que las consultas no se bloquean por escrituras. Esto pasa inadvertido para el usuario final y agrega muy poco trabajo extra al motor.

¿Pero no todas las funcionalidades básicas de la base de datos serían igual de importantes: respaldos, recuperación, paralelismo, transacciones distribuidas, y un largo etcétera?.

Después de descubrir que Oracle además implementa write-consistency - explicado con claridad por Tom Kyte acá y acá - se vuelve mi favorita por ser fundamental para la escalabilidad del motor, compleja y de elegante implementación, siendo un buen ejemplo de lo sofisticado que son los algoritmos incluidos en el motor y la importancia de que una base de datos tenga una arquitectura robusta.

Un saludo.

domingo, 2 de octubre de 2016

Validando inicio automático con scripts de Oracle en Linux

Hace poco tuve que revisar una base Oracle 11g en Linux que no estaba inciando cuando el servidor se reinciaba, a pesar de estar configurada para hacerlo.

Comparto la experiencia, ya que esto es algo bien simple pero que puede llevar algo de tiempo resolverlo ya que la documentación no es explícita en este punto: las entradas en /etc/oratab que configuran el inicio de una base no tienen que tener ningún comentario al final para que funcionen.

Esto quiere decir que esta entrada en /etc/oratab se ignora:
        TEST:/u01/app/oracle/product/11.2.0/db_1:Y               # line added by Agent

Contexto

Antes de ir al detalle, un poco de contexto: ¿cómo se puede configurar el inicio automático de una base de datos Oracle?. Hay dos opciones, dependiendo de si estamos usando clusterware o no:
  •  configurando scripts en /etc/init.d
  • Esta es la opción clásica desde 9i con algunas variantes
    Hay un muy buen blog post from Tim Hall explicando las opciones   
  • usando Oracle Clusterware
  • Desde 10g para base RAC o standalone.
    Notar que Oracle Restart (disponible desde 11g para standalone) es deprecado en 12c y se recomienda usar Clusterware con ASM en instalaciones standalone.
    Hay un muy buen post por Bjoern validando el uso de GI y otro de Bobby mostrando que se puede usar Restart en 12c
¿Cuál es la recomendación de Oracle en 12c para instalaciones no RAC? Usar scripts

Validando la configuración

El primer paso es validar que tenemos todo configurado para el incio automático:
  • el script dbora está instalado en /etc/init.d/dbora
  • la variable ORACLE_HOME tiene el path de nuestra instalación en ese script
  • los scripts dbshut y dbstart existen en nuestro Oracle home (vienen por defecto, pero por las dudas)
  • el script dbora está configurado para ejecutarse con el inicio y baja del SO
  • /etc/oratab tiene una entrada con "Y" para la base que queremos manejar con estos scripts
En mi caso, todo estaba en su lugar:
    [oracle@oraculo ~]$ cat /etc/init.d/dbora
    #!/bin/sh
    # chkconfig: 345 99 10
    # description: Oracle auto start-stop script.
    #
    # Change the value of ORACLE_HOME to specify the correct Oracle home
    # directory for your installation.

    ORACLE_HOME=/u01/app/oracle/product/11.2.0/db_1
    #
    # Change the value of ORACLE to the login name of the
    # oracle owner at your site.
    #
    ORACLE=oracle
    PATH=${PATH}:$ORACLE_HOME/bin
    export ORACLE_HOME PATH
    #

    case $1 in
    'start')
            runuser -l $ORACLE -c '$ORACLE_HOME/bin/dbstart $ORACLE_HOME &'
            touch /var/lock/subsys/dbora
            ;;
    'stop')
            runuser -l $ORACLE -c '$ORACLE_HOME/bin/dbshut $ORACLE_HOME'
            rm -f /var/lock/subsys/dbora
            ;;
    *)
            echo "usage: $0 {start|stop}"
            exit
            ;;
    esac
    #
    exit
   
    [oracle@oraculo ~]$ ls -lrt /u01/app/oracle/product/11.2.0/db_1/bin/dbstart
    -rwxr-x--- 1 oracle oinstall 13957 Sep  9  2014 /u01/app/oracle/product/11.2.0/db_1/bin/dbstart

    [oracle@oraculo ~]$ ls -lrt /u01/app/oracle/product/11.2.0/db_1/bin/dbshut*
    -rwxr-x---. 1 oracle oinstall 6030 Jan  1  2000 /u01/app/oracle/product/11.2.0/db_1/bin/dbshut

    [oracle@oraculo ~]$ chkconfig --list dbora
    dbora           0:off   1:off   2:off   3:on    4:on    5:on    6:off
   
    [oracle@oraculo ~]$ cat /etc/issue
    Red Hat Enterprise Linux Server release 6.6 (Santiago)
    Kernel \r on an \m

    [oracle@oraculo ~]$ tail /etc/oratab
    ##
    ## Multiple entries with the same $ORACLE_SID are not allowed.
    ##
    ##
    +ASM1:/u01/app/11.2.0/grid:N            # line added by Agent
    OLDT:/u01/app/oracle/product/11.2.0/db_1:N              # line added by Agent
    TEST:/u01/app/oracle/product/11.2.0/db_1:Y               # line added by Agent

Pero luego de reiniciar el servidor, la base no levantó.

Investigando el problema

Al ejectuar el script dbstart, se generan dos archivos de log:
    /u01/app/oracle/product/11.2.0/db_1/listener.log
    /u01/app/oracle/product/11.2.0/db_1/startup.log
En mi caso solo estaba creado el de listener, no el de la base.

Mirando el código del script dbstart, y después de habilitar trace agregando la variable ORACLE_TRACE=T en su código, algunos mensajes extras y reiniciar, encontré el problema en esta parte del código:
    ORACLE_SID=`echo $LINE | awk -F: '{print $1}' -`
    ...
    # Proceed only if last field is 'Y'.
    if [ "`echo $LINE | awk -F: '{print $NF}' -`" = "Y" ] ; then
 Validando ese código con nuestro archivo de configuración:
    [oracle@oraculo ~]$ cat /etc/oratab | awk -F: '{print $NF}' -
    #Backup file is  /u01/app/oracle/product/11.2.0/db_1/srvm/admin/oratab.bak.TESTlinux1 line added by Agent
    ##
    #
    #
    #
    ## This file is used by ORACLE utilities.  It is created by root.sh
    ## and updated by either Database Configuration Assistant while creating
    ## a database or ASM Configuration Assistant while creating ASM instance.
    #
    ## A colon is used as the field terminator.  A new line terminates
    ## the entry.  Lines beginning with a pound sign, '#', are comments.
    ##


    ##
    ## The first and second fields are the system identifier and home
    ## directory of the database respectively.  The third filed indicates
    ## to the dbstart utility that the database should , "Y", or should not,
    ## "N", be brought up at system boot time.
    ##
    ## Multiple entries with the same $ORACLE_SID are not allowed.
    ##
    ##
    N            # line added by Agent
    N              # line added by Agent
    Y               # line added by Agent

Cada línea es lo que se compara con "Y".
Para que ese código funcione, las líneas del archivo /etc/oratab deben terminar con la Y:

    [oracle@oraculo ~]$ echo "TEST:/u01/app/oracle/product/11.2.0/db_1:Y" | awk -F: '{print $NF}' -
    Y
Después de quitar los comentarios al final de la entrada en /etc/oratab, al siguiente reinicio del servidor ahora se reinicia la base:
    [oracle@oraculo ~]$ tail /etc/oratab
    ## "N", be brought up at system boot time.
    ##
    ## Multiple entries with the same $ORACLE_SID are not allowed.
    ##
    ##
    +ASM1:/u01/app/11.2.0/grid:N            # line added by Agent
    OLDT:/u01/app/oracle/product/11.2.0/db_1:N              # line added by Agent
    TEST:/u01/app/oracle/product/11.2.0/db_1:Y
   
    [oracle@oraculo ~]$ uptime
     12:13:10 up 4 days,  1:50,  1 user,  load average: 2.10, 1.31, 1.02

    [oracle@oraculo ~]$ ls -lrt /u01/app/oracle/product/11.2.0/db_1/startup.log
    -rw-r--r-- 1 oracle oinstall 2334 Sep 28 10:46 /u01/app/oracle/product/11.2.0/db_1/startup.log

    [oracle@oraculo ~]$ tail -17 /u01/app/oracle/product/11.2.0/db_1/startup.log
    ORACLE instance started.

    Total System Global Area 8017100800 bytes
    Fixed Size                  2244192 bytes
    Variable Size            1392509344 bytes
    Database Buffers         6610223104 bytes
    Redo Buffers               12124160 bytes
    Database mounted.
    SQL>
    Database altered.

    SQL> Disconnected from Oracle Database 11g Release 11.2.0.3.0 - 64bit Production
    + '[' 0 -eq 0 ']'
    + echo ''

    + echo '/u01/app/oracle/product/11.2.0/db_1/bin/dbstart: Database instance "TEST" warm started.'
    /u01/app/oracle/product/11.2.0/db_1/bin/dbstart: Database instance "TEST" warm started.
    [oracle@oraculo ~]$
Un saludo.   

martes, 12 de julio de 2016

Implementando row level security en Oracle

Me interesaba ponerme al día con las distintas opciones para implementar una solución de seguridad a nivel de registros en Oracle, un tema conocido con diferentes nombres: Virtual Private Database (VPD), Row Level Security (RLS) y Fine Grained Access Control (FGAC).

Este es un tema del que se ha hablado mucho, ya que desde la versión 8i (año 1999) Oracle tiene la funcionalidad VPD, agregando luego Label security (OLS).

Me tomé un tiempo para revisar que hay de nuevo en cada versión de Oracle sobre estas funcionalidades, para descubrir Real Application Security (RAS) en 12c que resuelve el tema con un enfoque más general separando seguridad de sesiones de esquemas.

Armé una presentación repasando las diferentes formas de implementar FGAC usando estas funcionalidades en base a ejemplos, y tuve la suerte de ser seleccionado para presentarla en el evento KScope16 organizado por ODTUG en Chicago hace unas semanas.

Dejo aquí los scripts SQL usados, y el link a la presentación.

Cada alternativa tiene muchos detalles y en esta presentación de 50 minutos apenas da para titulares, pero es una buena referencia para comenzar.

Un saludo.