15 noviembre 2016

PL / SQL: Evitar algoritmos innecesariamente complejos



Si tienes un equipo de  programadores nuevos en PL / SQL (y SQL), no es raro encontrar que complican demasiado las cosas, escribiendo más código de lo necesario y poniendo demasiada lógica en PL / SQL. Ese problema puede ser agravado por accidentalmente obtener la "respuesta correcta" basada en pruebas inadecuadas y datos de prueba.

Supongamos que tengo una tabla y un conjunto de datos como sigue:



# 1. Éxito accidental con datos de prueba incorrectos


CREATE TABLE undead_type
(
   undead_id     INTEGER PRIMARY KEY,
   undead_name   VARCHAR2 (100)
)
/

BEGIN
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (1, 'Skeleton');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (2, 'Zombie');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (3, 'Ghoul');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (4, 'Wight');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (5, 'Wraith');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (6, 'Mohrg');
  INSERT INTO undead_type (undead_id, undead_name)
        VALUES (7, 'Ghast');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (8, 'Mummy');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (9, 'Lich');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (10, 'Demilich');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (11, 'Vampire Spawn');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (12, 'Vampire');
   INSERT INTO undead_type (undead_id, undead_name)
        VALUES (13, 'Allip');
   COMMIT;
END;
/
Y tengo que escribir un programa que produce la siguiente salida: 
Undead en Orden Alfabético: 
  • Allip 
  • Demilich 
  • Ghast
  • ...
DECLARE
   l_count   INTEGER;
   l_name    plch_animals.animal_name%TYPE;
BEGIN
   DBMS_OUTPUT.put_line ('Animals in Alphabetical Order');

   SELECT COUNT (*) INTO l_count FROM plch_animals;

   FOR indx IN 1 .. l_count
   LOOP
      SELECT animal_name
        INTO l_name
        FROM plch_animals
       WHERE animal_id = indx;

      DBMS_OUTPUT.put_line (l_name);
   END LOOP;
END;
/

# 2. Demasiado SQL, datos insuficientes

DECLARE
   TYPE undead_ids_t IS TABLE OF undead_type.undead_id%TYPE;

   l_undead_ids   undead_ids_t;
   l_name         undead_type.undead_name%TYPE;
BEGIN
   DBMS_OUTPUT.put_line ('undead in Alphabetical Order');

   SELECT undead_id
     BULK COLLECT INTO l_undead_ids
     FROM undead_type;

   FOR indx IN 1 .. l_undead_ids.COUNT
   LOOP
      SELECT undead_name
        INTO l_name
        FROM undead_type
       WHERE undead_id = indx;

      DBMS_OUTPUT.put_line (l_name);
   END LOOP;
END;
/

# 3. Vamos a pasarlo bien con las conexiones PL/SQL con colecciones

DECLARE
   TYPE undead_ids_t IS TABLE OF undead_type.undead_id%TYPE
      INDEX BY undead_type.undead_name%TYPE;

   l_undead_ids   undead_ids_t;
   l_index        undead_type.undead_name%TYPE;
   l_name         undead_type.undead_name%TYPE;
BEGIN
   DBMS_OUTPUT.put_line ('undeads in Alphabetical Order');

   FOR rec IN (  SELECT *
                   FROM undead_type
               ORDER BY undead_name DESC)
   LOOP
      l_undead_ids (rec.undead_name) := rec.undead_id;
   END LOOP;

   l_index := l_undead_ids.FIRST;

   WHILE l_index IS NOT NULL
   LOOP
      DBMS_OUTPUT.put_line (l_index);

      l_index := l_undead_ids.NEXT (l_index);
   END LOOP;
END;
/

#4. SQL Simple

SELECT undead_name FROM undead_type
 ORDER BY undead_name;

No es mucho más simple que eso. Y si lo necesita dentro de PL / SQL

 #5. PL/SQL Simple

 BEGIN
   DBMS_OUTPUT.put_line ('undead in Alphabetical Order');

   FOR rec IN (SELECT undead_name FROM undead_type
                ORDER BY undead_name)
   LOOP
      DBMS_OUTPUT.put_line (rec.undead_name);
   END LOOP;
END;


Lecciones aprendidas 


  •  Deje a SQL hacer el levantamiento de pesas, tanto como sea posible (no es que haya algo muy "pesado" para levantar en este ejercicio!) 
  • No sobre-complicar las cosas. Asegúrese de que sus datos de prueba tengan suficiente volumen y variedad para ejercer realmente su algoritmo. 
  • Si te encuentras pensando "¿tiene que ser tan complicado?", Casi con toda seguridad la respuesta es un resonante "No!" Y debe dar un paso atrás, desafiar sus suposiciones, y ver cómo se puede simplificar su código

13 noviembre 2016

Oracle RAC for not so dummies

¿Qué es un Cluster?

Un clúster está formado por dos o más servidores independientes pero interconectados. 

Algunos clústeres están configurados de modo tal que puedan proveer alta disponibilidad permitiendo que la carga de trabajo sea transferida a un nodo secundario  si el nodo principal deja de funcionar. Otros clústeres están diseñados para proveer escalabilidad permitiendo que los usuarios o carga se distribuya entre los nodos. Ambas configuraciones son consideradas clústeres.

Una característica importante que tienen los clústeres es que se presentan a las aplicaciones como si fueran un solo servidor. Es deseable que la administración de diversos nodos de un clúster sea lo más parecida posible a la administración de una configuración de un solo nodo. El software de administración del clúster debería proveer este nivel de transparencia.

Para que los nodos puedan actuar como si fueran un solo servidor, los archivos deben estar almacenados de modo tal que puedan ser accedidos por todos los nodos del clúster.

En resumen, un clúster es un grupo de servidores independientes que cooperan comportándose como si fueran un solo sistema.

¿Qué es Oracle Real Application Clusters?

Real Application Clusters es un software que permite utilizar un clúster de servidores ejecutando múltiples instancias sobre una misma base de datos. Los archivos de base de datos quedan almacenados en discos física o lógicamente conectados a cada nodo, de modo tal que todas las instancias activas pueden leerlos o escribirlos.

El software de RAC maneja el acceso a los datos, de modo tal que los cambios en los datos son coordinados entre las instancias y cada instancia ve imágenes consistentes de la base. El interconnect del cluster permite que las instancias se pasen entre ellas información de coordinación e imágenes de los datos.

Esta arquitectura permite que los usuarios y aplicaciones se beneficien de la potencia de procesamiento de múltiples máquinas. La arquitectura RAC también ofrece redundancia; por ejemplo, en el caso de que un nodo quede inutilizado, la aplicación continuará accediendo a los datos vía el resto de las instancias disponibles.

Coordinación de recursos globales en un entorno RAC

En ambientes de una sola instancia, los mecanismos de bloqueo coordinan el acceso a recursos comunes como ser una simple fila de una tabla. Los mecanismos de lockeo previenen la posibilidad de que dos procesos modifiquen un mismo recurso al mismo tiempo.

En entornos RAC, la sincronización “internodo” es crítica para mantener una adecuada coordinación entre los distintos procesos en diferentes nodos, previniendo que estos procesos modifiquen el mismo recurso al mismo tiempo. La sincronización internodo garantiza que cada instancia vea la versión más reciente de un bloque de la buffer cache.
RAC utiliza lo que se conoce como Global Resource Directory (GRD) para registrar información sobre cómo los recursos son utilizados dentro de una base de datos en clúster. Global Cache Services (GCS) y Global Enqueue Services (GES) administran la información del GRD.

Cada instancia mantiene una parte de la GRD en su propia SGA. GCS y GES nominan a una instancia para administrar la información particular de un recurso. Esta instancia es llamada Resource Master. De este modo cada instancia sabe en qué instancia está masterizado cada recurso.

Mantener una cache coherente es también una parte muy importante dentro de la actividad de un RAC. El algoritmo Cache fusión es el encargado de mantener una cache coherente utilizando técnicas que mantienen múltiples copias consistentes de un mismo bloque entre diferentes instancias Oracle. Este algoritmo es implementado por GCS.
GES administra todos los recursos inter instancia que no maneja Oracle Fusión:
  • Dictionary cache locks,
  • Llibrary cache locks,
  • Deadlock detection.

Coordinación en el uso de la cache global.

Analizaremos un breve ejemplo puntual de coordinación del uso de la cache global.

El escenario planteado en este ejemplo es el siguiente:

  • Dos instancias en RAC. Nodo 1 y Nodo 2.
  • Un bloque de datos ha sido modificado (dirtied) por el Nodo 1.
  • El Nodo 2 intentará modificar el mismo bloque.
Veamos qué ocurre para que el Nodo 2 modifique el bloque:
  • El Nodo 2, que intenta modificar el bloque, submite un requerimiento a GCS.
  • GCS transmite el requerimiento al “holder” del recurso. En este caso, el Nodo 1 es el quien tiene el recurso.
  • El Nodo 1 recibe el mensaje y envía el bloque a la segunda instancia. El Nodo 1 mantiene el bloque “sucio” (también llamado “past image”).
  • Cuando el Nodo 2 recibe el bloque, informa a GCS que ahora es el “holder” del bloque. 


Reconfiguración dinámica del GRD (Global Resource Directory)





RAC utiliza el Global Resource Directory (GRD) para registrar información sobre cómo son utilizados los recursos dentro de una base de datos en clúster. Cada instancia mantiene una porción del GRD en su propia SGA.

Cuando una instancia abandona el clúster, es necesario redistribuir la porción del GRD que administraba entre los nodos sobrevivientes. Algo análogo ocurre cuando una nueva instancia se suma al clúster, las porciones del GRD de cada instancia necesitan redistribuirse para crear la nueva porción de GRD correspondiente a la instancia que se suma. 

En vez de remasterizar todos los recursos a través de todos los nodos, RAC utiliza un algoritmo denominado lazy remastering que remasteriza una cantidad mínima de recursos durante una reconfiguración.

Afinidad de objetos y remasterización dinámica

Global Cache Services (GCS), el encargado de administrar el Global Resource Directory (GRD) junto a Global Enqueue Services (GES), implementa un algoritmo para migrar dinámicamente recursos del GRD. 
A este algoritmo se lo conoce como remasterización dinámica. La idea básica de la remasterización dinámica es mantener un recurso de la buffer cache en la instancia que mas lo accede. GCS lleva un registro de los requerimientos por instancia y por objeto de modo tal que dispone de la información necesaria para migrar en forma dinámica recursos de una instancia a otra que lo accede más.


Memoria en una instalación de Oracle RAC

La memoria específica para la administración del RAC se aloca mayoritariamente en la Shared pool. Como los bloques pueden ser cacheados a través de las instancias es necesario contar también con buffer caches más grandes.

Al migrar un base de datos Oracle single instance a RAC, si se pretende que cada nodo mantenga su rendimiento con los mismos niveles de carga que en single instance, habrá que asignar un 10% más de memoria a la buffer cache y un 15% más a la shared pool. Estos valores son heurísticos, basados en experiencias de RAC a través del tiempo.

Sin embargo, hay que considerar que generalmente los requerimientos por instancia se ven reducidos cuando la misma cantidad de usuarios y carga de trabajo es distribuido en múltiples nodos.

Ejecución paralelizada en RAC

El optimizador basado en costos incorpora consideraciones de ejecución en paralelo a fin de obtener planes de ejecución óptimos.

En entornos RAC las decisiones del optimizador se hacen tanto a nivel intranodo como internodo. 
Por ejemplo, si una consulta requiere de 6 procesos para completar  su tarea y existen 6 procesos esclavos ociosos en el nodo local (el nodo al que está conectado el usuario) entonces la consulta se resuelve utilizando solamente recursos locales. De este modo se logra un paralelismo intranodo eficiente y se elimina el overhead que generaría una resolución internodo. 

Sin embargo, si existieran sólo 2 procesos esclavos ociosos en el nodo local, entonces se usarán los 2 procesos locales mas 4 de otro para completar el query. En este último caso se utiliza paralelismo intranodo e internodo a fin de acelerar el procesamiento.

Otro aspecto a considerar es que frecuentemente las consultas son particionados de forma perfecta entre los procesos esclavos; de modo tal que no todos terminan al mismo tiempo. La tecnología de procesamiento paralelo de Oracle detecta en forma dinámica el proceso que están ociosos porque ya finalizaron y vuelve a asignarle trabajo tomado de las tablas de colas de los procesos sobrecargados. De este modo Oracle redistribuye el trabajo en forma dinámica y eficiente entre todos los procesos.  

Procesos background en RAC.



En una configuración RAC aparecen una serie de nuevos procesos background. La función primaria de estos procesos es mantener una administración coherente entre todos los nodos que conforman el clúster: 

  • LMON. Global Enqueue Service Monitor 
  • LMD 0. Global Enqueue Service Daemon 
  • LMS x. Global Cache Service (x puede ir de 0 a n) 
  • LCK. Proceso de lockeo DIAG. 

Proceso de diagnóstico También aparecen nuevos procesos a nivel de clúster para la administración de Oracle Clusterware: 

  • CRSD y RACGIMON motores para operaciones de alta disponibilidad 
  • OCSSD provee accesos de membrecía a nodos y grupos de servicios 
  • EVMD detecta eventos y reacciona invocando procesos. 
  • OPROCD monitor de procesos del clúster (no esta presente en Linux ni Windows)

12 noviembre 2016

Oracle APEX, pequeña introducción

¿Que es APEX?

Oracle Application Express (ApEx) es una herramienta de desarrollo web que permite compartir datos y crear aplicaciones personalizadas de forma rápida. Con ayuda de un explorador web y sin necesidad de contar con conocimientos avanzados de programación, se podrán desarrollar y desplegar potentes aplicaciones, rápidas y seguras.
El desarrollo de aplicaciones con APEXestá basado en el explorador y permite desarrollar aplicaciones desde cualquier PC conectado en red,utilizando para ello tan sólo un explorador web actual. La tecnología APEX se basa y usa como núcleo SQL y PL / SQL. APEX es una herramienta declarativa que proporciona gran cantidad de características diseñadas para hacer el trabajo de desarrollo más fácil. El propio APEX se encarga de muchas de las funciones subyacentes comunes a todas las aplicaciones basadas en web; esto permite al programador centrarse en la lógica específica de la aplicación.
¿Cuáles son los requisitos?

  • Conocer sobre consultas SQL (básico) y programación con PL SQL (básico)
  • HTML, CSS (no excluyente)


Instalación de Oracle APEX 

Antes de instalar Oracle Application Express (Oracle APEX) es necesario:
  • Instalar base de datos Oracle (10g, 11g o 12c)

Estas son las versiones soportadas por Oracle APEX:
  • Linux x86
  • Linux x86-64
  • Oracle Solaris on SPARC (64 bit)
  • Oracle Solaris x86-64 (64 bit)
  • HP-UX Itanium
  • Microsoft Windows (32-bit)
  • Microsoft Windows x64 (64-bit)
  • IBM AIX on POWER Systems (64-bit)
  • IBM: Linux on System z
  • HP-UX PA-RISC (64-bit)
Descomprima el archivo zip que ha descargado en alguna posición de la unidad de disco duro. Aquí lo descomprimo en C: / DevProgram

A continuación, introduzca la sentencia sqlplus para iniciar sesión en sqlplus (Nota: no abra sqlplus directamente, sino a través de CMD después de posicionarse en el APEX home)




--
-- Run script apexins.sql with parameters:
--
-- @apexins.sql tablespace_apex tablespace_files tablespace_temp images
--
-- Where:
-- tablespace_apex is the name of the tablespace for the Oracle Application Express application user.
-- tablespace_files is the name of the tablespace for the Oracle Application Express files user.
-- tablespace_temp is the name of the temporary tablespace or tablespace group.
-- images is the virtual directory for Oracle Application Express images.
-- (To support future Oracle Application Express upgrades, define the virtual image directory as /i/.)
--
 
@apexins.sql sysaux sysaux temp /i/
El script anterior crea un SCHEMA en la base de datos, puede probar consultando Ver ALL_USERS en SQLPlus




--
-- Running script apex_epg_config.sql with parameter:
-- @apex_epg_config.sql parent of apex directory
--
 
@apex_epg_config.sql C:\DevPrograms

Habilitar usuario anonymous

--
-- Unlock user anonymous:
 alter user anonymous account unlock;

apexconf.sql 

 Ejecutar script apexconf.sql Se utiliza para realizar los pasos finales de configuración de Oracle Application Express, incluida la configuración del puerto de escucha HTTP XDB ​​y la contraseña ADMIN de Application Express.


--
-- Running script: @apxconf.sql
-- Setup password for ADMIN
-- Configuring XDB Http Listener port
--
 
@apxconf.sql

El usuario, puede usar ADMIN de forma predeterminada y el correo electrónico puede omitirse. Para la contraseña, el sistema requiere que ingrese una contraseña segura: 

  • La contraseña no se ajusta a las reglas de complejidad de contraseñas de este sitio. 
  • La contraseña debe contener al menos 6 caracteres.
  • La contraseña debe contener al menos un carácter alfabético (abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ). 
  • La contraseña debe contener al menos un carácter de puntuación (! "# $% & ()` '* +, - /:;? _).
  • La contraseña debe contener al menos un carácter alfabético en mayúsculas. 
  • La contraseña debe contener al menos un carácter alfabético en minúsculas.


El puerto predeterminado es 8080

Vamos a un navegador y tecleamos



Introducimos clave y usuario.




11 noviembre 2016

Error ORA-38856 cuando duplicas una base de datos 11gR2 en entorno de alta disponibilidad

¿Qué hacer cuando duplicas una base de datos Oracle aparece este tipo de error en un entorno RAC?




En estos días, repasando mis Oracle skills, he estado clonando una bases de datos en RAC 11gR2 con el siguiente script:


RUN
{
ALLOCATE AUXILIARY CHANNEL CH1  TYPE DISK ;
ALLOCATE AUXILIARY CHANNEL CH2  TYPE DISK ;
DUPLICATE DATABASE TO TESTDB
  BACKUP LOCATION '/mount/harkonnen/copia01/originales/'
  DB_FILE_NAME_CONVERT '+DATA/ORIGINAL/DATAFILE','+DATA/TESTDB/DATAFILE'
  PFILE '/mount/dba01/oracle/TESTDB/pfile/initTESTDB1.ora'
  NOFILENAMECHECK
  NOREDO
LOGFILE
  GROUP 1 (
    '+DATA/TESTDB/ONLINELOG/redo01g1.log',
    '+DATA/TESTDB/ONLINELOG/redo02g1.log'
  ) SIZE 300M ,
  GROUP 2 (
    '+DATA/TESTDB/ONLINELOG/redo01g2.log',
    '+DATA/TESTDB/ONLINELOG/redo02g2.log'
  ) SIZE 300M
 ;

Al acabar la clonación, justo al abrir la base de datos, sucedio el siguiente error:



contents of Memory Script:
{
   Alter clone database open resetlogs;
}

alter database open resetlogs
*
ERROR at line 1:
ORA-38856: cannot mark instance UNNAMED_INSTANCE_2 (redo thread 2) 

Buceando en la inmensa Oracle Support encontré la nota 334899.1, en la que marca que podemos utilizar el siguiente parámetro:


_no_recovery_through_resetlogs=TRUE

Una vez que cambie el parámetro, volvi a lanzar la clonación de la base de datos, y esta vez acabo sin ningún problema

Error ORA-01503 y ORA-12720 cuando clonas una BD en entornos de alta disponibilidad

¿Qué hacer cuando mientras clonas una base de datos Oracle aparece este tipo de error en una implantación RAC?


RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of Duplicate Db command at 10/07/2016 13:31:14
RMAN-06136: ORACLE error from auxiliary database: ORA-01503: CREATE CONTROLFILE failed
ORA-12720: operation requires database is in EXCLUSIVE mode

Se ha de cambiar el parámetro cluster_database a falso:

alter system set cluster_database=FALSE scope=spfile sid='INSTANCE_NAME';

Una vez que hayas terminado con el proceso de clonación, tienes que regresar el parámetro a verdadero para que esta instancia siga siendo parte de tu configuración de RAC.


alter system set cluster_database=TRUE scope=spfile sid='INSTANCE_NAME';

Java Forensics en bases de datos Oracle

Esta vez quiero mostrar cómo determinar si los ataques de privilegio de Java se han producido en su base de datos, tanto como medida de precaución como para el análisis forense después del incidente, con el fin de verificar si un ataque de esta naturaleza ha ocurrido o no.

En primer lugar veamos la situación en la que un atacante utiliza DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY para concederse a sí mismos cualquier privilegio Java de CREATE SESSION debido a ejecutar DBMS_JVM_EXP_PERMS.

Si su base de datos está recogiendo mensajes de error a continuación, busca errores del tipo ORA-29532:

SQL> DECLARE  
  2  POL DBMS_JVM_EXP_PERMS.TEMP_JAVA_POLICY;  
  3  CURSOR C1 IS SELECT 'GRANT','JAVATEST','SYS','java.io.FilePermission','$','execute',
                        'ENABLED' FROM DUAL;  
BEGIN  
OPEN C1;  
  4    5  FETCH C1 BULK COLLECT INTO POL;  
  6  CLOSE C1;  
DBMS_JVM_EXP_PERMS.IMPORT_JVM_PERMS(POL);  
  7    8  END;  
  9  / 10  
DECLARE  
*  
ERROR at line 1:  
ORA-29532: Java call terminated by uncaught Java exception:  
java.lang.SecurityException: policy table update java.lang.RuntimePermission,  
loadLibrary.*  
ORA-06512: at "SYS.DBMS_JVM_EXP_PERMS", line 189  
ORA-06512: at line 8 
La escalada de privilegios aún ha tenido éxito por lo que el mensaje de error es un poco engañoso, pero podría ser un indicador útil.

SQL>  SELECT TYPE_NAME, NAME, ACTION FROM USER_JAVA_POLICY WHERE GRANTEE_NAME ='JAVATEST';  
  
TYPE_NAME  
--------------------------------------------------------------------------------  
NAME  
--------------------------------------------------------------------------------  
ACTION  
--------------------------------------------------------------------------------  
java.io.FilePermission  
 $ 
execute  

Vamos a centrarnos en la identificación de la escalada de privilegios de Java. 
Una vez que se han asignado privilegios de Java existen múltiples formas de utilizar el privilegio de ganar SYSDBA, y una vez adquirido, el atacante tendría limpiar el rastro que habían dejado atrás, primero instalando un rootkit, y luego revocar privilegios y eliminando las cuentas que se crearon en el camino. 

Así, el reto de un investigador forense es buscar pistas que un atacante puede no haber sido lo suficientemente diligente para limpiar. 

Así, en primer lugar, ¿cómo podemos saber si un usuario se ha concedido privilegios Java? DBA_JAVA_POLICY es la vista fundamental, y esto muestra amablemente todos los privilegios concedidos por orden cronológico de Java utilizando el número de secuencia de incrementar…


SELECT TYPE_NAME, NAME, ACTION FROM USER_JAVA_POLICY WHERE GRANTEE_NAME ='JAVATEST';  
  
TYPE_NAME  
--------------------------------------------------------------------------------  
NAME  
--------------------------------------------------------------------------------  
ACTION  
--------------------------------------------------------------------------------  
java.io.FilePermission  
ALL FILES
execute 
Así que si un atacante sabe esto, es probable que ha ga drop de a cuenta de ataque y lo recrea si es necesario como parte de un ataque posterior. Sin embargo, si nos fijamos en la tabla base sys.java $ policy $ para la vista DBA_JAVA_POLICY, veremos que la tabla realmente persiste en las concesiones de Java, incluso después de que el usuario haya sido eliminado !!! Esto es útil para una investigación posterior a incidentes.


SELECT * FROM sys.java$policy$ ORDER BY key DESC;  
  
KIND#   GRANTEE#    TYPE_SCHEMA#    TYPE_NAME   NAME    ACTION  STATUS# KEY  
-----------------------------------------------------------------------------------------------------  
0   101 0   java.io.FilePermission  ALL FILES   execute 2   282  
0   100 0   java.io.FilePermission  ALL FILES   execute 2   262  
0   54  0   java.io.FilePermission  ALL FILES   execute 2   242  
  
--Note that the GRANTEE# correlates to the sys.user$.USER# column and we can see   
-- that user 101 and 100 both had execute on ALL FILE   
-- ,but these users no longer exist in sys.user$ and still the privs are recorded in sys.java$policy$ ~which could be very useful info..  
  
SQL> select name from sys.user$ where user# in (101, 100);  
  
no rows selected  
  
SQL> select name from sys.user$ where user# in (54);  
  
NAME  
------------------------------  
SCOTT  
  
--Of course a clever attacker that had gained SYS could delete from the base table..  
  
SQL> delete from sys.java$policy$ where key='242';  
  
1 row deleted.  
  
SQL> commit;  
  
Commit complete.  
  
--And the evidence of the escalation has gone.. How would an investigator see that the table had been modified in this case?   
--Tracing back further it would hopefully be possible to use the dba_tab_modifications view:  
  
SQL> SELECT * FROM dba_tab_modifications WHERE table_name='JAVA$POLICY$'  
  2  ;  
  
no rows selected  
--This empty result set is due to the fact that MONITORING is not set on this table by default. This could be rectified as follows in this example.  
SQL> exec dbms_stats.gather_table_stats ('SYS','JAVA$POLICY$');  
  
PL/SQL procedure successfully completed.  
  
SQL> delete from sys.java$policy$ where key='282';  
  
0 rows deleted.  
  
SQL>  delete from sys.java$policy$ where key='242';  
  
1 row deleted.  
  
SQL> execute dbms_stats.flush_database_monitoring_info;  
  
PL/SQL procedure successfully completed.  
  
SQL> SELECT * FROM dba_tab_modifications WHERE table_name='JAVA$POLICY$';  
  
TABLE_OWNER     TABLE_NAME      PARTITION_NAME      SUBPARTITION_NAME  INSERTS    UPDATES    DELETES TIMESTAMP TRU DROP_SEGMENTS  
------------------------------ ------------------------------ ------------------------------ ------------------------------ ---------- ----------   
SYS                 JAVA$POLICY$                                           0          0          1        31-MAR-10 NO              0  
  
--It is unlikely that a DB will have had this default setting changed beforehand though..   
--So what else can be done to see if the DBA_JAVA_POLICY table has been changed recently?  
  
SQL> select scn_to_timestamp(Max(ora_rowscn)) from sys.java$policy$;  
  
SCN_TO_TIMESTAMP(MAX(ORA_ROWSCN))  
-----------------------------------------------------  
30-MAR-10 06.10.06.000000000 PM  

Nota: esta consulta normalmente trabajará hasta 7 días después de que el cambio haya ocurrido, por lo que si obtiene este error ORA-08181 la tabla probablemente no ha tenido comandos de manipulación de datos (DML) en él durante ese tiempo.

ORA-08181: specified number is not a valid system change number

10 noviembre 2016

Nuevos parámetros SPFILE en base de datos Oracle 12.2.0.1

La Base de Datos Oracle 12.2.0.1 está disponible ahora en la nube de Oracle.

Y esta es la lista de los 46 nuevos parámetros init.ora / spfile comparados con la base de datos Oracle 12.1.0.2. Ojo que algunos de ellos están sin documentar a día de hoy.


Parameter
Description
allow_global_dblinks
ALLOW_GLOBAL_DBLINKS specifies whether LDAP lookup for database links is allowed for the database.
allow_group_access_to_sga
ALLOW_GROUP_ACCESS_TO_SGA controls group access to shared memory on UNIX platforms.

The default value is false, which means that database shared memory is created with owner access only. In Oracle Database releases prior to Oracle Database 12c Release 2 (12.2.0.1), database shared memory was created with owner and group access.
approx_for_aggregation
APPROX_FOR_AGGREGATION replaces exact query processing for aggregation queries with approximate query processing.

Data analysis applications heavily use aggregate function and analytic function queries. Aggregation functions and analytic functions require sorting of large volumes of data, and exact query answering requires lots of memory, and can be time consuming. With approximate query processing, the results of aggregate function and analytic function queries are returned much faster than with exact query processing.
approx_for_count_distinct
APPROX_FOR_COUNT_DISTINCT automatically replaces COUNT (DISTINCT expr) queries with APPROX_COUNT_DISTINCT queries.

Query results for APPROX_COUNT_DISTINCT queries are returned faster than the equivalent COUNT (DISTINCT expr) queries. APPROX_COUNT_DISTINCT queries are useful for situations where a tolerable amount of error is acceptable in order to obtain faster query results than with a COUNT (DISTINCT expr) query.
approx_for_percentile
APPROX_FOR_PERCENTILE converts exact percentile functions to their approximate percentile function counterparts.

Approximate percentile function queries are faster than their exact percentile function query counterparts, so they can be useful in situations where a tolerable amount of error is acceptable in order to obtain faster query results.
asm_io_processes
ASM_IO_PROCESSES specifies the number of I/O worker processes to be started in an Oracle Automatic Storage Management (Oracle ASM) IOServer instance.

This parameter is applicable only in an Oracle ASM IOServer instance, which runs out of an Oracle Grid home.

The default value should work in most cases
autotask_max_active_pdbs
AUTOTASK_MAX_ACTIVE_PDBS enables you to specify the maximum number of PDBs that can schedule automated maintenance tasks at the same time (during a maintenance window).
This parameter only affects PDBs. The CDB$ROOT container (CDB root) for a CDB can always schedule and run maintenance tasks during a maintenance window.
The default value is 2.
awr_pdb_autoflush_enabled
AWR_PDB_AUTOFLUSH_ENABLED enables you to specify whether to enable or disable automatic Automatic Workload Repository (AWR) snapshots for all the PDBs in a CDB or for individual PDBs in a CDB. Default value is false.
cdb_cluster
[undocumented]
cdb_cluster_name *
[undocumented]
clonedb_dir *
CLONEDB_DIR sets the directory path where CloneDB bitmap files should be created and accessed.
By default the CloneDB bitmap file is created under the $ORACLE_HOME/dbs directory.
containers_parallel_degree
CONTAINERS_PARALLEL_DEGREE can be used to control the degree of parallelism of a query involving containers(). The value of containers_parallel_degree, if set, will override the default DOP for a containers() query.
By default, a containers() query uses a degree of parallelism equal to (1 + number of open PDBs) in the case of CDB root and (1 + number of open application PDBs) in the case of application root.
If the value of CONTAINERS_PARALLEL_DEGREE is lower than 65535, then this value is used as the degree of parallelism of a query involving  containers(). Otherwise (when the value is 65535), the default degree of parallelism is (1 + number of open PDBs) or (1 + number of open application PDBs) as described above.
cursor_invalidation
CURSOR_INVALIDATION controls whether deferred cursor invalidation or immediate cursor invalidation is used for DDL statements by default.
data_guard_sync_latency
Data Guard SYNC latency
data_transfer_cache_size
DATA_TRANSFER_CACHE_SIZE sets the size of the data transfer cache (in bytes) used to receive data blocks (typically from a primary database in an Oracle Data Guard environment) for consumption by an instance during execution of an RMAN RECOVER ... NONLOGGED BLOCK command
default_sharing
DEFAULT_SHARING sets the value of the sharing clause in statements creating objects in an application root.
Specifying SHARING= in the create DDL overrides the value of the DEFAULT_SHARING parameter.
disable_pdb_feature *
 [undocumented]
enable_automatic_maintenance_pdb
Enable/Disable Automated Maintenance for Non-Root PDB
enable_dnfs_dispatcher
Enable DNFS Dispatcher
enabled_PDBs_on_standby
List of Enabled PDB patterns
encrypt_new_tablespaces
whether to encrypt newly created tablespaces
exafusion_enabled
Enable Exafusion
external_keystore_credential_location
external keystore credential location
inmemory_adg_enabled
Enable IMC support on ADG
inmemory_expressions_usage
Controls which In-Memory Expressions are populated in-memory
inmemory_virtual_columns
Controls which user-defined virtual columns are stored in-memory
instance_abort_delay_time
time to delay an internal initiated abort (in seconds)
instance_mode
indicates whether the instance read-only or read-write or read-mostly
long_module_action
Use longer module and action
max_datapump_jobs_per_pdb
maximum number of concurrent Data Pump Jobs per PDB
max_idle_time
maximum session idle time in minutes
max_iops
MAX IO per second
max_mbps
MAX MB per second
max_pdbs
max number of pdbs allowed in CDB or Application ROOT
ofs_threads
Number of OFS threads
one_step_plugin_for_pdb_with_tde *
[undocumented] Facilitate one-step plugin for PDB with TDE encrypted data
optimizer_adaptive_plans
controls all types of adaptive plans
optimizer_adaptive_statistics
controls all types of adaptive statistics
outbound_dblink_protocols
Outbound DBLINK Protocols allowed
remote_recovery_file_dest
default remote database recovery file location for refresh/relocate
resource_manage_goldengate
RESOURCE_MANAGE_GOLDENGATE determines whether Oracle GoldenGate apply processes in the database are resource managed.

To enable Resource Manager, set the RESOURCE_MANAGER_PLAN parameter.

By default, Oracle GoldenGate apply processes in the database are not resource managed. Given that replication to a PDB requires a separate Oracle GoldenGate apply process,
sga_min_size
SGA_MIN_SIZE sets the guaranteed SGA size for a pluggable database (PDB). When SGA_MIN_SIZE is set for a PDB, it guarantees the specified SGA size for the PDB.
Setting this parameter at the CDB level has no effect.
shrd_dupl_table_refresh_rate
duplicated table refresh rate (in seconds)
standby_db_preserve_states
STANDBY_DB_PRESERVE_STATES is meaningful on a physical standby database that is open in real-time query mode. The parameter controls whether user sessions and other internal states of the instance are retained when a readable physical standby database is converted to a primary database.

The possible values for the parameter are NONE, SESSION, and ALL
target_pdbs*
 [undocumented] Parameter is a hint to adjust certain attributes of the CDB
uniform_log_timestamp_format
UNIFORM_LOG_TIMESTAMP_FORMAT specifies that a uniform timestamp format be used in Oracle Database trace (.trc) files.

When the value of UNIFORM_LOG_TIMESTAMP_FORMAT is TRUE, the format used for timestamps in trace files is standardized on universal time with millisecond precision.