martes 23 de junio de 2009

Arreglando el error: ORA-27102: out ot memory en Oracle y Solaris 10

Al cambiar los archivos de una base de datos Oracle en un servidor con Solaris 9 a uno con Solaris 10 y querer levantarla me encontré con el siguiente error
SQL> startup
ORA-27102: out of memory
SVR4 Error: 22: Invalid argument




según el mensaje de error el servidor no tiene memoria suficiente, veamos que dice la documentación al respecto
$ oerr ORA 27102
27102, 00000, "out of memory"
// *Cause: Out of memory
// *Action: Consult the trace file for details

nada alentador el panorama. Revisemos lo último que se registró en el archivo alert.log
$ cat alert.log
Fri Jun 5 18:19:45 2009
Starting ORACLE instance (normal)
Fri Jun 5 18:19:46 2009
WARNING: EINVAL creating segment of size 0x000000008c400000
fix shm parameters in /etc/system or equivalent

Oracle está tratando de crear un segmento de memoria compartida de 2G (dependiendo del tamaño de SGA/PGA), pero el sistema operativo respondió con un mensaje de error de argumento no válido (EINVAL). Se muestra además una pequeña pista sobre configurar los parámetros shm en /etc/system.

Antes de Solaris 10, se configuraba el parámetro shmsys:shminfo_shmmax en /etc/system con el tamaño máximo de segmento de memoria que puede crearse. El valor por default en Solaris 9 y versiones anteriores es de 8M; mientras que en Solaris 10 o superior es 1/4 de la memoria física. Lo puedes verificar de la siguiente manera:
$ prtconf | grep Mem
Memory size: 2048 Megabytes
$ id -p
uid=110(oracle) gid=201(dba) projid=3(default)
$ prctl -n project.max-shm-memory -i project 3
project: 3: default
NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
project.max-shm-memory
        privileged      479M        -   deny                                 -
        system          16.0EB    max   deny                                 -

He ahí el problema, el sistema está usando el valor por default de 479M para este caso, cuando Oracle está tratando de crear un segmento de memoria (2G) mayor a 479M.

La solución es configurar el sistema con un tamaño suficientemente grande para que el segmento de memoria compartida sea creado y Oracle pueda levantar la instancia.

En Solaris 9 y versiones anteriores, esto puede hacerse agregando la siguiente línea en /etc/system, teniendo que reiniciar el sistema para que tome el nuevo valor.
set shminfo_shmmax = 0x000000008c400000

En Solaris 10 el parámetro shminfo_shmmax es obsoleto y Sun no recomienda configurarlo en /etc/system aún a pesar de que funcione como se espera.

En Solaris 10 y posterior, este valor puede cambiarse dinámicamente por proyecto con la ayuda de los servicios de control de recursos. Así es como se hace en Solaris 10 y posterior
$ prctl -n project.max-shm-memory -r -v 2G -i project 3
$ prctl -n project.max-shm-memory -i project 3
NAME    PRIVILEGE       VALUE    FLAG   ACTION                       RECIPIENT
project.max-shm-memory
        privileged      2.0G        -   deny                                 -
        system          16.0EB    max   deny                                 -

Todos los cambios hechos con el comando prctl se aplican al sistema de manera temporal por lo que se perderán cuando se reinicie. Para hacerlo permanente, crea un proyecto con el comando projadd
$ projadd -p 200 -c 'Oracle config' -U oracle -G dba -K 'project.max-shm-memory=(privileged,2G,deny)' oracle

Finalmente cerciórate que fue creado con el comando projects -l ó cat /etc/project
$ projects -l
...
...
oracle
        projid : 200
        comment: "Oracle config"
        users  : oracle
        groups : dba
        attribs: project.max-shm-memory=(priv,2147483648,deny)
$ cat /etc/project
...
...
oracle:200:Oracle config:oracle:dba:project.max-shm-memory=(priv,2147483648,deny)

Con estos cambios, Oracle debería arrancar la base de datos de manera normal.
SQL> startup
ORACLE instance started.

Total System Global Area 2333054160 bytes
Fixed Size                   734416 bytes
Variable Size            1191182336 bytes
Database Buffers         1073741824 bytes
Redo Buffers               67395584 bytes
Database mounted.
Database opened.

Otro caso que puede presentar el mismo síntoma es cuando aumentas la SGA en la instancia resultado posiblemente de un tuning el cual si es mayor al segmento de memoria configurada para el sistema, cuando intentes levantar la instancia tendrá este mismo comportamiento.

Vía
Mandalika's scratchpad