CRS falla al arrancar con el error CRS-6706: Oracle Clusterware Release patch level

Hoy vamos a ver una sencilla entrada que puede ocurrirnos al parchear el ASM

Los recursos de crs no levantan y recibimos el eror

[testserver]$ sudo $ORACLE_HOME/bin/crsctl start has
CRS-6706: Oracle Clusterware Release patch level ('3930441427') does not match Software patch level ('526767740'). Oracle Clusterware cannot be started.
CRS-4000: Command Start failed, or completed with errors.

En este caso oracle nos recomienda que desbloqueemos el crs y repitamos los pasos .
Aunque en la nota de oracle nos indiquen ejecutar

# /crs/install/roothas.sh -patch

Este es un comando muy vago, por lo que, mi recomendacion es, sabiendo donde ha fallado, ejecutar el pre o ppost pach

[testserver]$ sudo $ORACLE_HOME/crs/install/roothas.sh -prepatch
Using configuration parameter file: /u01/app/oracle/product/19c/grid/crs/install/crsconfig_params
The log of current session can be found at:
  /u01/app/oracle/crsdata/icdbstst01/crsconfig/hapatch_2023-08-09_10-55-17AM.log
2023/08/09 10:55:29 CLSRSC-347: Successfully unlock /u01/app/oracle/product/19c/grid
2023/08/09 10:55:29 CLSRSC-671: Pre-patch steps for patching GI home successfully completed.

[testserver]$ sudo $ORACLE_HOME/crs/install/roothas.sh -postpatch
Using configuration parameter file: /u01/app/oracle/product/19c/grid/crs/install/crsconfig_params
The log of current session can be found at:
  /u01/app/oracle/crsdata/icdbstst01/crsconfig/hapatch_2023-08-09_10-55-36AM.log
2023/08/09 10:55:40 CLSRSC-329: Replacing Clusterware entries in file 'oracle-ohasd.service'
2023/08/09 10:58:01 CLSRSC-672: Post-patch steps for patching GI home successfully completed.

[testserver]$ sudo $ORACLE_HOME/bin/crsctl start has
CRS-4640: Oracle High Availability Services is already active
CRS-4000: Command Start failed, or completed with errors.

Como veis, nada de que asustarse con los comandos indicados

Mas information en soporte con la nota

  • CRS-6706: Oracle Clusterware Release patch level (‘nnn’) does not match Software patch level (‘mmm’) (Doc ID 1639285.1)

Como crear un asm sin tener discos

Hoy vamos a ver como hacerle trampas a Oracle para levatar una instancia de ASM sin tener discos en el servidor.

Supongamos que el ORACLE_HOME del grid lo tenemos en /u01/app/oracle/product/19c/grid, los pasos a seguir serian


-- == Fake disk 
sudo dd if=/dev/zero of= /u01/app/oracle/product/19c/grid/ASMFAKE.img bs=1M count=5000
sudo losetup /dev/loop1  /u01/app/oracle/product/19c/grid/ASMFAKE.img
 

  
sudo /usr/sbin/asmtool -C -l /dev/oracleasm -n FAKE1  -s /dev/loop1 -a force=yes
sudo /usr/sbin/oracleasm scandisks
sudo /usr/sbin/oracleasm listdisks

Con esto, cuando ejecutemos el asmca vermos que hay un disco llamado FAKE1 que no es otra cosa que el disc ASMFAKE que hemos creado.

Creación de Discos y ASM con Ansible

Siguiendo con las entradas de Aprovisionamiento de una base de datos con ansible vamos a ver la manera de automatizar la configuracion de discos de ASM mediante ansible.

Supongamos tenemos los prerrequisitos:

  • Un servidor OEL7 con el CRS instalado y el listener en marcha tal y como explicabamos en Instalando el grid infraesturcure con Ansible
    • Dos discos para nuestro diskgroup DATA
    • un disco para nuestro diskgroup FRA
    • un disco para nuestro diskgroup REDO1
    • un disco para nuestro diskgroup REDO2

        Para la ejecucion de nuestro taller de creacion de asm usaremos los siguientes ficheros del repositorio

        Raiz
        |
        |- vars:
             |- oracle_standard.yaml      Fichero con los estandares del departamento
        |
        |- templates
        |
         |- files
         |-REQ01_asm_create_disks.yaml  Ejemplo de informacon de  provisionamiento de discos para el ASM 
        |  
        | asmlib_configure.yaml         Playbook que configura el asmlib
        | asmlib_create_disks.yaml      Playbook que configura los discos de ASM 
        | asm_create.yaml               Playbook que crea una instancia +ASM con en el GRID y con los discos previamente instalados
        

        Ficheros de variables

        Al igual que en el resto de ejecuciones del taller vamos a necesitar el fichero oracle_standard.yaml que contiene todas la estandarizacion de nuestro departamento

        Ficheros informacion

        La creacion de discos necesita de la informacion de que discos del sistema operativo van a ir dedicados a que diskgroup, esta informacion la depositaremos en el directorio files, que va a ser el unico directorio donde deberemos/podremos modificar los ficheros .

        El formato del fichero sera el de una lista en yaml en el que indicaremos el nombre del dispositivo para cada uno de los diskgroups.
        [code lang=»py»]
        DATA:
        – /dev/sda
        – /dev/sdb
        FRA:
        – /dev/sdc
        REDO1:
        – /dev/sdd
        REDO2:
        – /dev/sde
        [/code]

        El nomre del fichero sera [REQ]_asm_create_disks. Donde REQ es el valor en mayusculas de la variable req que es el identificador unico de nuestro fichero, este identificador en un entorno de produccion real podria corresponderse con el numero de peticion del sistema gestion de la compañia.

        Creacion de los discos

        Una vez tenemos claros los ficheros de fuentes y variables ejecutaremos nuestros playbooks.

        asmlib_configure.yaml

        El playbook asmlib_configure.yaml vieje a ser el equialente a la ejecucion manual de oracleasm configure -i
        Como podeis ver en el codigo que es bastante basico, ejecuta la configuracion del oracleasm para cada uno de los campos obteniendo la informacion del fichero de variables generico

        [code lang=»py»]
        # Pamplona 2019
        # Playbook which configures_asmlib
        #
        # requires
        # env: name of the server which should be in the inventory
        # vars/oracle_standard.yaml configuration file with all the deppartment values

        – hosts: "{{env}}"
        remote_user: ansible
        become: yes
        become_user: root
        tasks:
        – fail: msg="Error no server definied, please define the env variable in the job"
        when: env is not defined

        – name: "Including standard variables"
        include_vars:
        file: "vars/oracle_standard.yaml"
        – name: configirando usuario
        command: /usr/sbin/oracleasm configure -u "{{oracle_user}}"

        – name: configurando grupo
        command: /usr/sbin/oracleasm configure -g "{{oracle_group}}"

        – name: seteamos al arranque
        command: /usr/sbin/oracleasm configure -e

        – name: activamos el logical block
        command: /usr/sbin/oracleasm configure -b

        – name: arrancamos
        command: /usr/sbin/oracleasm init

        – name: estado
        command: /usr/sbin/oracleasm status
        register: oasm_status

        [/code]

        asmlib_create_disks.yaml

        El segundo paso es la creacion de los discos en el asmlib .
        Este es el playbook que va a requerir de ese fichero externo [REQ]_asm_create_disks, para cada uno de los discos fisios incluidos.

        [code lang=»py»]
        # Pamplona 2019
        # Playbook which checks if the hosts has all the requested prerequisites
        #
        # requires
        # env: name of the server which should be in the inventory
        # REQ: number of request
        # vars/oracle_standard.yaml configuration file with all the department values

        – hosts: "{{env}}"
        remote_user: ansible
        become: yes
        become_user: root
        tasks:
        – fail: msg="Error no server definied, please define the env variable or de request number in the job"
        when: env is not defined or req is not defined

        – name: "Including standard variables"
        include_vars:
        file: "vars/oracle_standard.yaml"

        – name: "Including So {{version}} requisites"
        include_vars:
        file: "files/{{req|upper}}_asm_create_disks.yaml"

        – name: creating DATA disks
        shell:
        cmd: "/usr/sbin/asmtool -C -l /dev/oracleasm -n {{oracle_hostname|upper}}_DATA0{{ansible_loop.index}} -s {{item}} -a force=yes "
        loop: "{{DATA}}"
        loop_control:
        extended: yes

        – name: Creating FRA disks
        shell:
        cmd: "/usr/sbin/asmtool -C -l /dev/oracleasm -n {{oracle_hostname|upper}}_FRA0{{ansible_loop.index}} -s {{item}} -a force=yes "
        loop: "{{FRA}}"
        loop_control:
        extended: yes

        – name: Creating REDO1 disks
        shell:
        cmd: "/usr/sbin/asmtool -C -l /dev/oracleasm -n {{oracle_hostname|upper}}_REDO1_{{ansible_loop.index}} -s {{item}} -a force=yes "
        loop: "{{REDO1}}"
        loop_control:
        extended: yes

        – name: Creating REDO2 disks
        shell:
        cmd: "/usr/sbin/asmtool -C -l /dev/oracleasm -n {{oracle_hostname|upper}}_REDO2_{{ansible_loop.index}} -s {{item}} -a force=yes "
        loop: "{{REDO2}}"
        loop_control:
        extended: yes

        – name: scanning disks
        shell:
        cmd: "/usr/sbin/oracleasm scandisks"

        [/code]
        debilidades
        -Como curiosidad podeis ver que en mi taller no sigo las normativa de oracle, llamando a los diskgroups HOSTNAME_DATA en ved de DATA y manteniendo 2 grupos de REDO en ved e uno.
        -Este playbook solamente puede usarse para provisionamiento y no para añadir nuevos discos a un diskgroup ya exsistente ya que numerara los discos empezando desde cero. (uso del fact ansible_loop.index)

        Creacion del asm

        Llegados a este punto, tenemos el grid corriendo, el listener arriba y los dispositivos creados , por lo que solamente nos queda el crear el ASM
        El siguiente playbook simplemente va a llevar a cabo una creacion del ASM en modo command line silent y añadirle los discos a sus respectivos diskgroups

        [code lang=»py»]
        # Pamplona 2020
        # Playbook which creates a database
        #
        # requires
        # env: name of the server which should be in the inventory
        # vars/oracle_standard.yaml standard values for Oracle
        #

        – hosts: "{{env}}"
        vars:
        type: asm
        remote_user: ansible
        tasks:

        # checking prerequisites
        – fail:
        msg: "Error no server defined, please define the env variable in the job"
        when: env is not defined

        # Loading env
        – name: Including Standard_values
        include_vars:
        file: "vars/oracle_standard.yaml"

        – name: checking oratab
        shell:
        cmd: "cat /etc/oratab|grep +ASM |sed -e ‘s/# line added by Agent/ /g’ -e ‘s/:/ /g’|awk ‘{ print $1}’ "
        register: count

        – fail:
        msg: "ERROR: The chain {{item}} exists at {{env}} /etc/oratab file "
        when: item == "+ASM"
        with_items:
        – "{{count.stdout_lines}}"

        – set_fact:
        oracle_home: "{{oracle_home_directory.asm}}"
        when: type == ‘asm’

        – name: Creating syslog file
        copy:
        dest: /etc/rsyslog.d/30-oracle.conf
        content: |
        "local0.info {{oracle_home}}/rdbms/audit/asmaudit.log
        &~"
        force: yes
        become: yes
        become_user: root

        – name: Creating logrotate file
        copy:
        dest: /etc/logrotate.d/30-oracle_logs
        content: |
        "{{oracle_home}}/rdbms/audit/asmaudit.log {
        weekly
        rotate 4
        compress
        copytruncate
        delaycompress
        notifyempty
        }"
        force: yes
        become: yes
        become_user: root

        – name: create ASM
        become: yes
        become_user: "{{oracle_user}}"
        shell:
        cmd: "{{ oracle_home }}/bin/asmca -silent
        -configureASM
        -sysAsmPassword {{sysasm_passd}}
        -asmsnmpPassword {{asmdbsnmp_passwd}}
        -diskString \"/dev/oracleasm/disks/*\"
        -diskGroupName {{oracle_hostname|upper}}_DATA
        -disk \"/dev/oracleasm/disks/{{oracle_hostname|upper}}_DATA*\"
        -param ASM_POWER_LIMIT=1
        -param DIAGNOSTIC_DEST={{oracle_base}}
        -param AUDIT_SYSLOG_LEVEL=’local0.info’
        -param AUDIT_SYS_OPERATIONS=TRUE
        -redundancy EXTERNAL"

        – name: Create FRA, REDO1 and REDO2
        become: yes
        become_user: "{{oracle_user}}"
        shell:
        cmd: "{{ oracle_home }}/bin/asmca -silent
        -createDiskGroup
        -sysAsmPassword {{sysasm_passd}}
        -diskString \"/dev/oracleasm/disks/*\"
        -diskGroupName {{oracle_hostname|upper}}_{{item}}
        -disk \"/dev/oracleasm/disks/{{oracle_hostname|upper}}_{{item}}*\"
        -redundancy EXTERNAL "
        with_items:
        – FRA
        – REDO1
        – REDO2
        [/code]

Usando los bloques logicos en ASM

Hoy vamos a ver una entrada que nos puede causar grandes dolores de cabeza .

Uno de los problemas con los que nos podemos encontrar cuando se modifica la tecnología de los discos físicos utilizados en el ASM es el cambio del tamaño de bloque lógico.

Supongamos que nos ofrecen un nuevo disco /dev/xvdz

Nosotros intentamos añadirlo al ASM, pero recibimos un error ORA-01378

Errors in file /u01/app/oracle/diag/rdbms/test/TEST/trace/TEST_ora_40862.trc:
ORA-01378: The logical block size (512) of file +REDO is not compatible with the disk sector size 
(media sector size is 4096 and host sector size is 4096)

Veamos las características de este disco

sudo fdisk -l /dev/xvdz
Disk /dev/xvdd: 21.5 GB, 21474836480 bytes
255 heads, 63 sectors/track, 2610 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk identifier: 0x00000000

Y veamos ahora otro de los discos que tenemos

The other disks  have sector size 512
Disk /dev/xvdp: 2147.5 GB, 2147483648000 bytes
255 heads, 63 sectors/track, 261083 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

Si nos fijamos, el problema que tenemos es que el sector size de nuestro nuevo disco es 8 veces mayor que el del disco viejo (521 / 4096) .

Como solucionamos ahora nuestro problema?

Tal y como indican el el blog flashdba ASM tiene un parámetro en el fichero de configuración llamado ORACLEASM_USE_LOGICAL_BLOCK_SIZE que por defecto esta a false, que era el parámetro por defecto de oracleasm-support-2.1.8.
Podemos ver su valor en el fichero /etc/sysconfig/oracleasm

# ORACLEASM_USE_LOGICAL_BLOCK_SIZE: 'true' means use the logical block size
# reported by the underlying disk instead of the physical. The default
# is 'false'
ORACLEASM_USE_LOGICAL_BLOCK_SIZE=false

Lo que vamos ha hacer es modificarlo a TRUE, de manera que el ASM sea capaz de usar los bloques de manera lógica y no se aferre a la configuración física de los mismos, esto lo hacemos con el script
oracleasm-configure.sh

  • -b|—logical-blocks sets logical blocksize usage
  • -p|—physical-blocks set physical blocksize usage

Veamos ahora cual es la información que nos dará nuestro ASM

[oracle@testserver ~]$ sysasm
 SQL> select NAME,SECTOR_SIZE,BLOCK_SIZE,DATABASE_COMPATIBILITY,COMPATIBILITY,((TOTAL_MB-FREE_MB)*100/TOTAL_MB) PERCENT_USED from v$asm_diskgroup;

NAME         SECTOR_SIZE BLOCK_SIZE DATABASE_COMPATIBILI COMPATIBILITY        PERCENT_USED
-------------------- --------- ---------- -------------------- -------------------- ------------
REDO               4096       4096 10.1.0.0.0           10.1.0.0.0             .249023438
FRA                 512       4096 10.1.0.0.0           12.1.0.0.0             44.1858724
DATA                512       4096 11.2.0.0.0           11.2.0.0.0             90.4637587

Como podeis ver, es un problema que se nos puede dar en bases de datos con ASM antiguos en los que llevemos a cabo un cambio de tecnología física.

Mas informacion en

Oracle ASMLib: Physical and Logical Blocksize

Renombrado un ASM diskgroup

Hoy vamos a ver una entrada muy rapida sobre como renombrar un diskgroup exsistente en ASM.

Lo primero que tenemos que tener en cuenta es que , deberemos de parar todas las bases de datos que esten escribiendo sobre ese diskgroup.

Para nuestro caso hemos creado un grupo llamado WRONG_DATA01


test1.pamplona.name:oracle  crsctl stat res -t
--------------------------------------------------------------------------------
Name           Target  State        Server                   State details
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.LISTENER.lsnr
               ONLINE  ONLINE       test1                STABLE
ora.WRONG_DATA01.dg
               OFFLINE OFFLINE      test1                STABLE
ora.test1_FRA_01.dg
               OFFLINE OFFLINE      test1                STABLE
ora.test1_REDO_01.dg
               ONLINE  OFFLINE      test1                STABLE
ora.test1_REDO_02.dg
               OFFLINE OFFLINE      test1                STABLE
ora.asm
               ONLINE  OFFLINE      test1                Instance Shutdown,STARTING
ora.ons
               OFFLINE OFFLINE      test1                STABLE
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.cssd
      1        ONLINE  ONLINE       test1                STABLE
ora.diskmon
      1        OFFLINE OFFLINE                               STABLE
ora.evmd
      1        ONLINE  INTERMEDIATE test1                STABLE
--------------------------------------------------------------------------------

Lo primero y mas logico, es que deberemos de desmontar el dislkgroup a renombrar

test1.pamplona.name:oracle  srvctl stop  diskgroup -diskgroup WRONG_DATA01

test1.pamplona.name:oracle  crsctl stat res -t
--------------------------------------------------------------------------------
Name           Target  State        Server                   State details
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.LISTENER.lsnr
               ONLINE  ONLINE       test1                STABLE
ora.WRONG_DATA01.dg
               OFFLINE OFFLINE      test1                STABLE
ora.test1_FRA_01.dg
               ONLINE  ONLINE       test1                STABLE
ora.test1_REDO_01.dg
               ONLINE  ONLINE       test1                STABLE
ora.test1_REDO_02.dg
               ONLINE  ONLINE       test1                STABLE
ora.asm
               ONLINE  ONLINE       test1                Started,STABLE
ora.ons
               OFFLINE OFFLINE      test1                STABLE
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.cssd
      1        ONLINE  ONLINE       test1                STABLE
ora.diskmon
      1        OFFLINE OFFLINE                               STABLE
ora.evmd
      1        ONLINE  ONLINE       test1                STABLE
--------------------------------------------------------------------------------

Una vez desmontado, procedermos a renombrarlo.
EL renombrado cuenta con dos fases

  • Fase 1 : Esta fase solamente genera el fichero de configuracion
  • Fase 2 Basandose en la fase uno lleva a cabo el cambio .

Veamos a cabo como se lleva a cabo.

Fase 1

A pesar de ser la fase 1 la llamaremos como phase=both y añadiremos el flag check=true , esto nos asegura que no llevara a cabo cambios en las cabeceras de los discos ASM .

renamedg phase=both dgname=WRONG_DATA01 newdgname=test1_DATA_01 asm_diskstring=’/dev/oracleasm/disks/’ check=true verbose=true

test1.pamplona.name:oracle  renamedg phase=both dgname=WRONG_DATA01 newdgname=test1_DATA_01 asm_diskstring='/dev/oracleasm/disks/' check=true verbose=true
Parsing parameters..
Parameters in effect:

         Old DG name       : WRONG_DATA01
         New DG name          : test1_DATA_01
         Phases               :
                 Phase 1
                 Phase 2
         Discovery str        : /dev/oracleasm/disks/
         Check              : TRUE
         Clean              : TRUE
         Raw only           : TRUE
renamedg operation: phase=both dgname=WRONG_DATA01 newdgname=test1_DATA_01 asm_diskstring=/dev/oracleasm/disks/ check=true verbose=true
Executing phase 1
Discovering the group
Performing discovery with string:/dev/oracleasm/disks/
Identified disk UFS:/dev/oracleasm/disks/test1_DATA_01_0001 with disk number:0 and timestamp (33066256 1704307712)
Identified disk UFS:/dev/oracleasm/disks/test1_DATA_01_0002 with disk number:1 and timestamp (33066256 1704307712)
Checking for hearbeat...
Re-discovering the group
Performing discovery with string:/dev/oracleasm/disks/
Identified disk UFS:/dev/oracleasm/disks/test1_DATA_01_0001 with disk number:0 and timestamp (33066256 1704307712)
Identified disk UFS:/dev/oracleasm/disks/test1_DATA_01_0002 with disk number:1 and timestamp (33066256 1704307712)
Checking if the diskgroup is mounted or used by CSS
Checking disk number:0
Checking disk number:1
Generating configuration file..
Completed phase 1
Executing phase 2
Looking for /dev/oracleasm/disks/test1_DATA_01_0001
Leaving the header unchanged
Looking for /dev/oracleasm/disks/test1_DATA_01_0002
Leaving the header unchanged
Completed phase 2
Terminating kgfd context 0x7fb9d6aff0a0

Esta fase nos habra dejado un fichero de configuracion llamado renamedg_config

Fase 2

Este es el comendo que realmente nos llevara a cabo el cambio


renamedg phase=two dgname=WRONG_DATA01 newdgname=test1_DATA_01 asm_diskstring=’/dev/oracleasm/disks/’ verbose=true config=’./renamedg_config’

importanteComo podeis ver es muy sencillo, pero es muy importante tener en cuenta que, este cambio solo se lleva a cabo a nivel de sistema operativo y ASM , no a nivel de ficheros de configuracion o de base de datos, por lo que tendreis que revisar:

  • Ubicacion de pfiles y spfiles
  • Ubicacion de controlfiles dentro de los ficheros de arranque
  • Ubicacion de ficheros de base datos (datafiles,tempfiles, redologs)