PiensoPienso: Como hacer una reorganización de cambio de tipo de datos, sin interrumpir la operativa.
Problema:
Tengo una KB GeneXus, con una tabla con 2 millones de registros que tiene un campo AttSec N(3) y debe cambiarse a C(3) (si se quiere, puede tener otro nombre).
Tabla
======
*Clave N(10)
AttSec N(3)
otros atributos
El sistema esta funcionando 24x7, se instala en varios nodos (en un NLB).
La aplicación deberá estar operativa siempre, no se puede bajar ni bloquear.
Se pide:
¿Cuales son los pasos de desarrollo e instalación que debo seguir para lograr instalar en todos los nodos la aplicación operativa con el atributo C(3)?
Solución:
Si alguien se anima, la escribe en los comentarios.
Yo publico la mia en unos dias.
UPDATE = 04/07/2017===============================
MI SOLUCIÓN:
Lo primero que haría seria ver si la tabla es usada solo por mi aplicación o también es accedida por alguna aplicación externa. Para simplificar, supongamos que solo es accedida por la aplicación GeneXus.
T ambien agrego un trigger para que si se inserta o actualiza el campo AttSec, le cargue un valor char a AttSecChar.
El pseudocodigo del trigger, seria algo así: Disparar en Insert y Update
Si AttSecChar es Nulo
AttSecChar = AttSec.ToString()
sino AttSec = AttSecChar.ToNumber() finsi
No debe cancelar bajo ningun error (por ejemplo, si se le pasa un char que no es un numero al ToNumber() debera grabar un valor por defecto y dejar un rastro para poder chequearlo.
Hay que testearlo muy bien, con diferentes valores posibles tanto de AttSec y AttSecChar
where AttSecChar.IsEmpty() or Null
AttSec=AttSec
commit
endfor
for each
AttSec <> val(AttSecChar) Msg(format('Quedo mal el registro %1 - Valor Numerico %2 - Valor Char %3',Clave,AttSec,AttSecChar),status)
endfor
Con este paso, tendriamos la tabla con los dos campos (el C(3) y N(3) ) inicializados, y sincronizados ante casi cualquier cambio.
En la KB, renombro el atributo AttSec a AttSecChar y le cambio el tipo de datos de N(3) a C(3)
Especifico, corrijo todos los errores de especificación y compilación que aparezcan.
Prueba la aplicación. Instalo en uno de los Nodos y pruebo.
Si todo funciona bien, sigo con el resto de los nodos.
Tener en cuenta
Asegurarse que nadie este accediendo al campo AttSec. Si no aparece ningun acceso al campo en 15 dias, pasar al paso siguiente. Si aparece algo, corregirlo.
Da la sensación que muchos de estos pasos son automatizables y que podrían ser incorporados en las herramientas que manejan el deploy de aplicaciones.
Es un lindo desafío lograr que esto suceda en los próximos años.
Tengo una KB GeneXus, con una tabla con 2 millones de registros que tiene un campo AttSec N(3) y debe cambiarse a C(3) (si se quiere, puede tener otro nombre).
Tabla
======
*Clave N(10)
AttSec N(3)
otros atributos
El sistema esta funcionando 24x7, se instala en varios nodos (en un NLB).
La aplicación deberá estar operativa siempre, no se puede bajar ni bloquear.
Se pide:
¿Cuales son los pasos de desarrollo e instalación que debo seguir para lograr instalar en todos los nodos la aplicación operativa con el atributo C(3)?
Solución:
Si alguien se anima, la escribe en los comentarios.
Yo publico la mia en unos dias.
UPDATE = 04/07/2017===============================
MI SOLUCIÓN:
Lo primero que haría seria ver si la tabla es usada solo por mi aplicación o también es accedida por alguna aplicación externa. Para simplificar, supongamos que solo es accedida por la aplicación GeneXus.
Estado Inicial
Agrego un campo AttSecChar C(3)
T ambien agrego un trigger para que si se inserta o actualiza el campo AttSec, le cargue un valor char a AttSecChar.
El pseudocodigo del trigger, seria algo así: Disparar en Insert y Update
Si AttSecChar es Nulo
AttSecChar = AttSec.ToString()
sino AttSec = AttSecChar.ToNumber() finsi
No debe cancelar bajo ningun error (por ejemplo, si se le pasa un char que no es un numero al ToNumber() debera grabar un valor por defecto y dejar un rastro para poder chequearlo.
Hay que testearlo muy bien, con diferentes valores posibles tanto de AttSec y AttSecChar
Inicializo el campo AttSecChar
Se ejecuta un programa que recorra 10 registros y actualice AttSec. Esto fuerza que se dispare el trigger y se inicialice el campo. De esta forma, no vamos a bloquear los registros por mucho tiempo El codigo seria algo asi for eachwhere AttSecChar.IsEmpty() or Null
AttSec=AttSec
commit
endfor
for each
AttSec <> val(AttSecChar) Msg(format('Quedo mal el registro %1 - Valor Numerico %2 - Valor Char %3',Clave,AttSec,AttSecChar),status)
endfor
Con este paso, tendriamos la tabla con los dos campos (el C(3) y N(3) ) inicializados, y sincronizados ante casi cualquier cambio.
Cambiar la KB y la programación.
En la KB, renombro el atributo AttSec a AttSecChar y le cambio el tipo de datos de N(3) a C(3)
Especifico, corrijo todos los errores de especificación y compilación que aparezcan.
Prueba la aplicación. Instalo en uno de los Nodos y pruebo.
Si todo funciona bien, sigo con el resto de los nodos.
Actualizar otras aplicaciones.
En este momento, hay que avisar a todos los desarrolladores de otras aplicaciones que estén accediendo a dicha tabla que deben hacer también el cambio.Tener en cuenta
- Herramientas de Reporting / BI
- Herramientas de Monitoreo
- Consultas Ad-hoc en la base de datos
- Vistas/Triggers
Habilitar auditoria en la base de datos.
Asegurarse que nadie este accediendo al campo AttSec. Si no aparece ningun acceso al campo en 15 dias, pasar al paso siguiente. Si aparece algo, corregirlo. Renombro el atributo viejo y borrar el trigger.
Este paso es opcional, pero me gusta tenerlo, por si hay que volver atras en forma rapida, si aparece algun contratiempo.Borrar el atributo no usado.
Conclusiones
Todos estos pasos son los que considero necesarios para permitir hacer reorganizaciones con aplicaciones funcionando.Da la sensación que muchos de estos pasos son automatizables y que podrían ser incorporados en las herramientas que manejan el deploy de aplicaciones.
Es un lindo desafío lograr que esto suceda en los próximos años.
Pensando en el aire...
ResponderBorrar0) "Reorg" agrego nuevo campo C(3), formula (str(pkvieja)) (solo para que en paso 2, gx haga el populate de los registros)
1) reorg campo c(3) deja de ser formula, se agrega hace indice unique, cambios en programas que hacen insert en la tabla para que pongan valor a ambos campos
2) Reorg cambio de pk y programas que accedan la tabla para entrar por nueva pk (dejan de nombrar al campo viejo)
3) (opcional) reorg quita el campo viejo
Me gustaría una solución con menos reorgs... lo bueno es que se pueden ir aplicando de a poco, no importa cuanto tiempo pase entre cada paso...
La "implementacion" dependerá mucho de la BD, porque la parte de "millones" de registros, hace que cada "reorg" sea fragil en tiempos
BorrarEs verdad.. lo quise dejar bastante genérico.. para poder pensar en forma amplia.
BorrarPongamos que tiene 2 millones de registros, y correr la reorganizacion que plantea GeneXus, demora 10 minutos. No se puede tener 10 minutos aplicacion sin funcionar.
O sea, solo se pueden ejecutar reorganizaciones Genexus que mantengan compatibilidad hacia atras de la base de datos.
habria que hacerla a mano :s
BorrarEso, seguro te evita "reorgs intermedias"... igualmente, de "agregar la columna" (con un alter add column, no con un tabla intermedia y copia) no nos salvamos, y cuanto tarda eso depende de la bdd, pero le lleva (me acuerdo de alguna version de mysql, que por mas que era un add column, internamente estaba implementado (por mysql) con una tabla intermedia y copia)