Implementación de Flyway para Tibero y contribución Open Source
Compartiendo la experiencia de implementar la herramienta de migración Flyway para base de datos Tibero y contribuir al código abierto.
Introducción
En este artículo, me gustaría compartir el proceso de aplicar Flyway para la gestión de versiones DDL de la base de datos Tibero usada en nuestra empresa, y la experiencia posterior de contribución al código abierto.
Problemas existentes
Cuando me uní al proyecto, había los siguientes problemas relacionados con la gestión de bases de datos:
- Código DDL legacy excesivo
- Modificaciones frecuentes de esquema debido a cambios en requisitos de servicio
- Inicialización frecuente de base de datos en entornos de desarrollo y local
- Mayor riesgo de error humano por modificación y ejecución manual de DDL
- Gestión DDL desorganizada
- Acumulación masiva de archivos DDL
- Adiciones/modificaciones/eliminaciones DDL descontroladas basadas en requisitos del equipo
- Trabajo de cambio de esquema concentrado en individuos específicos
- Disminución de productividad de desarrollo
- Dificultad en cambios de esquema DB entre entornos (desarrollo-staging-producción)
- Mayor carga en separación de DB
- Complejidad en configuración del entorno de desarrollo
Eventualmente, pensé que estos problemas llevarían seriamente a una disminución de la productividad de desarrollo como se muestra abajo.
Solución
Para resolver estos problemas, consideré introducir Flyway, una librería de control de versiones de DB que había usado antes, lo que significaba sin curva de aprendizaje y aplicación rápida.
Sin embargo, hubo un nuevo problema de que Flyway no soporta oficialmente Tibero…
No solo nuestro equipo sino otros desarrolladores con las mismas necesidades en GitHub confirmaron este issue, y mirando la respuesta del mantenedor de Flyway, parecía no haber planes de soporte futuro. Considerando las similitudes sintácticas entre Oracle y Tibero, que ya está soportado,
Pensé que necesitaba implementarlo yo mismo para prevenir issues de DB Migration que podrían ocurrir fácilmente en la situación actual.
Establecimiento de objetivos del proyecto
Los miembros de nuestro equipo estuvieron de acuerdo, y comenzamos el proyecto con los siguientes objetivos:
Proceso de implementación
Nuestro objetivo fue implementar 6 de los comandos básicos de Flyway (baseline, migrate, clean, info, validate, repair), excluyendo ‘undo’ que es una característica de la versión Pro.
Como hay mucho contenido de implementación, en lugar de describir todo en el blog, me centraré en las partes que diferían de Oracle y las dificultades encontradas con sus soluciones.
Primero, la parte más consumidora de tiempo y difícil de la implementación fue el comando clean.
Como la función clean de Flyway elimina todos los objetos de esquema, necesita verificar la existencia de cada objeto de esquema y eliminarlos.
En este proceso, las diferencias entre Tibero y Oracle fueron prominentes (nombres de objetos de esquema, métodos de consulta, objetos no soportados, etc.) eran diferentes entre las dos bases de datos,
así que tuve que revisar cuidadosamente la documentación oficial de Tibero y escribir sentencias de consulta apropiadas para cada objeto.
1. Diferencias entre Oracle y Tibero en Flyway Clean
Por ejemplo, Oracle usa ALL_SDO_GEOM_METADATA para consultar metadatos específicos, pero en Tibero, teníamos que usar el correspondiente ALL_GEOMETRY_COLUMNS.
Como se muestra abajo, mirando la implementación del método flyway clean de Oracle, hay una tarea para eliminar locatorMetadata primero antes de la operación clean:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private boolean locatorMetadataExists() throws SQLException {
return database.queryReturnsRows("SELECT * FROM ALL_SDO_GEOM_METADATA WHERE OWNER = ?", name);
}
private void cleanLocatorMetadata() throws SQLException {
if (!locatorMetadataExists()) {
return;
}
if (!isDefaultSchemaForUser()) {
LOG.warn("Unable to clean Oracle Locator metadata for schema " + database.quote(name) +
" by user \"" + database.doGetCurrentUser() + "\": unsupported operation");
return;
}
jdbcTemplate.getConnection().commit();
jdbcTemplate.execute("DELETE FROM USER_SDO_GEOM_METADATA");
jdbcTemplate.getConnection().commit();
}
Para Tibero, la parte correspondiente a ALL_SDO_GEOM_METADATA es ALL_GEOMETRY_COLUMNS, así que necesitábamos agregar el trabajo para eliminar esa parte.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void cleanLocatorMetadata() throws SQLException {
if (!locatorMetadataExists()) {
return;
}
if (!isDefaultSchemaForUser()) {
return;
}
jdbcTemplate.getConnection().commit();
jdbcTemplate.execute("DELETE FROM USER_GEOMETRY_COLUMNS");
jdbcTemplate.getConnection().commit();
}
private boolean locatorMetadataExists() throws SQLException {
return database.queryReturnsRows("SELECT * FROM ALL_GEOMETRY_COLUMNS WHERE F_TABLE_SCHEMA = ?",
name);
}
También, para queueTable, hay consideraciones al vaciar en Tibero: oracle, tibero - queue table
- Para queue_table, en Tibero también se consulta en all_tables, así que necesitamos agregar consulta para excluirlo si también se consulta en all_queue_tables
- Para queue_table, un lob index también se crea al crear, y el lob index asociado se elimina automáticamente al eliminar la queue table
- Por lo tanto, al consultar objetos index, los lob indexes deben excluirse para prevenir errores
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Todos los indexes, excepto domain indexes y lob indexes, deben eliminarse después de las tablas (si quedan).
INDEX("INDEX") {
@Override
public List<String> getObjectNames (JdbcTemplate jdbcTemplate, TiberoDatabase database,
TiberoSchema schema) throws SQLException {
return jdbcTemplate.queryForStringList(
"SELECT INDEX_NAME FROM ALL_INDEXES WHERE OWNER = ?" +
" AND INDEX_NAME NOT LIKE 'SYS_C%'" +
" AND INDEX_TYPE NOT LIKE '%DOMAIN%'" +
" AND INDEX_TYPE NOT LIKE '%LOB%'",
schema.getName()
);
}
}
Además de estos, me referí a la documentación oficial de Tibero y probé yo mismo las partes sintácticamente diferentes
para implementar las características de Flyway.
Ver implementación detallada aquí
2. Prueba de Flyway Tibero con Testcontainers
Finalmente, para que los miembros del equipo y todos los que usen este código implementado confíen y lo usen, escribir código de prueba era esencial.
El problema era que Tibero no tiene una docker image oficial, y testcontainers tampoco soporta Tibero como módulo, así que ambos necesitaban implementación…
En este artículo, solo dejaré enlaces a recursos implementados exitosamente y publicados públicamente
tibero-docker - github
testcontainers-tibero - github
Esta parte continuará en el siguiente artículo…
Contribución Open Source
Como el Flyway implementado para Tibero fue usado dentro del equipo, funcionó sin problemas como el equipo originalmente pretendía, y otros equipos pudieron aplicarlo fácilmente basándose en la documentación.
Por lo tanto, decidimos hacer una contribución open source con acuerdo, para ayudar a desarrolladores que usan Tibero y tienen las mismas necesidades que nosotros.
Conclusión
La contribución open source fue mi segunda contribución open source después de la localización coreana de MDN,
y creo que las partes que implementamos (tibero-docker, tibero flyway) ayudaron al equipo y también ayudaron a llenar la brecha de conocimiento de Tibero que tenía mientras desarrollaba.





