Hibernate: hbm2ddl.auto = ¿actualizar en producción?

¿Está bien ejecutar aplicaciones de Hibernate configuradas con hbm2ddl.auto=update para actualizar el esquema de la base de datos en un entorno de producción?

No, no es seguro.

A pesar de los mejores esfuerzos del equipo de Hibernate, simplemente no puede confiar en las actualizaciones automáticas en producción . Escriba sus propios parches, revíselos con DBA, pruébelos y luego aplíquelos manualmente.

Teóricamente, si la actualización de hbm2ddl funcionó en el desarrollo, también debería funcionar en la producción. Pero en realidad, no siempre es el caso.

Incluso si funcionó bien, puede ser subóptimo. A los DBA se les paga mucho por una razón.

Lo hacemos en producción, aunque con una aplicación que no es crítica para la misión y sin DBA altamente remunerados en el personal. Es solo un proceso manual menos que está sujeto a error humano: la aplicación puede detectar la diferencia y hacer lo correcto, además de que presumiblemente lo ha probado en varios entornos de desarrollo y prueba.

Una advertencia: en un entorno agrupado, es posible que desee evitarlo porque pueden aparecer varias aplicaciones al mismo tiempo e intentar modificar el esquema, lo que podría ser malo. O ponga en algún mecanismo donde solo una instancia puede actualizar el esquema.

Los creadores de Hibernate desalientan a hacerlo en un entorno de producción en su libro “Java Persistence with Hibernate” :

ADVERTENCIA: hemos visto a los usuarios de Hibernate intentando usar SchemaUpdate para actualizar automáticamente el esquema de una base de datos de producción. Esto puede terminar rápidamente en un desastre y no será permitido por su DBA.

Consulte LiquiBase XML para mantener un registro de cambios. Nunca lo había usado hasta este año, pero descubrí que es muy fácil de aprender y hacer que el control de revisiones / migración / gestión de cambios de DB sea muy infalible. Trabajo en un proyecto de Groovy / Grails, y Grails usa Hibernate debajo para todo su ORM (llamado “GORM”). Usamos Liquibase para administrar todos los cambios de esquema SQL, lo cual hacemos con bastante frecuencia a medida que nuestra aplicación evoluciona con nuevas funciones.

Básicamente, mantiene un archivo XML de conjuntos de cambios que continúa agregando a medida que su aplicación evoluciona. Este archivo se guarda en git (o lo que sea que esté usando) con el rest de su proyecto. Cuando se implementa su aplicación, Liquibase comprueba su tabla de registro de cambios en la base de datos a la que se está conectando para que sepa qué se aplicó, luego aplica inteligentemente los conjuntos de cambios que aún no se hayan aplicado desde el archivo. Funciona de maravilla en la práctica, y si lo usa para todos sus cambios de esquema, puede estar 100% seguro de que el código que finalice la compra y la implementación siempre podrá conectarse a un esquema de base de datos totalmente compatible.

Lo asombroso es que puedo tomar una base de datos mysql de pizarra totalmente en blanco en mi computadora portátil, iniciar la aplicación y de inmediato el esquema está configurado para mí. También facilita la prueba de los cambios de esquema al aplicarlos a un db local o de desarrollo primero.

La forma más fácil de comenzar con esto sería tomar su DB existente y luego usar Liquibase para generar un archivo baseline.xml inicial. Luego, en el futuro, puede agregarlo y dejar que liquibase se encargue de administrar los cambios de esquema.

http://www.liquibase.org/

Yo votaría no. Hibernate no parece entender cuándo han cambiado los tipos de datos para las columnas. Ejemplos (usando MySQL):

 String with @Column(length=50) ==> varchar(50) changed to String with @Column(length=100) ==> still varchar(50), not changed to varchar(100) @Temporal(TemporalType.TIMESTAMP,TIME,DATE) will not update the DB columns if changed 

Probablemente también haya otros ejemplos, como boost la longitud de una columna String por encima de 255 y verla convertir a texto, texto medio, etc., etc.

Por supuesto, no creo que haya realmente una forma de “convertir tipos de datos” sin crear una nueva columna, copiar los datos y eliminar la antigua columna. Pero en el momento en que su base de datos tiene columnas que no reflejan el mapeo actual de Hibernate, está viviendo muy peligrosamente …

Flyway es una buena opción para lidiar con este problema:

http://flywaydb.org

Hibernate tiene que poner la advertencia sobre no usar actualizaciones automáticas en prod para cubrirse cuando las personas que no saben lo que están haciendo lo usan en situaciones donde no se debe usar.

Debo admitir que las situaciones en las que no se deben usar son mucho más numerosas que las que están bien.

Lo he usado durante años en muchos proyectos diferentes y nunca he tenido un solo problema. Esa no es una respuesta floja, y no es una encoding vaquera. Es un hecho histórico.

Una persona que dice “nunca lo haga en producción” está pensando en un conjunto específico de despliegues de producción, es decir, aquellos con los que está familiarizado (su empresa, su industria, etc.).

El universo de “despliegues de producción” es vasto y variado.

Un desarrollador experimentado de Hibernate sabe exactamente qué DDL resultará de una configuración de mapeo determinada. Siempre y cuando pruebes y valides que lo que esperas termina en el DDL (en desarrollo, qa, assembly, etc.), estás bien.

Cuando agrega muchas funciones, las actualizaciones automáticas de esquema pueden ahorrarle tiempo.

La lista de cosas que las actualizaciones automáticas no manejarán es interminable, pero algunos ejemplos son la migración de datos, la adición de columnas que no admiten nulos, los cambios en el nombre de la columna, etc., etc.

También debe tener cuidado en entornos agrupados.

Pero, de nuevo, si supieras todo esto, no harías esta pregunta. Hmm. . . De acuerdo, si hace esta pregunta, debe esperar hasta que tenga mucha experiencia con Hibernate y las actualizaciones automáticas del esquema antes de pensar en usarlo en prod.

Lo hacemos en un proyecto que se ejecuta en producción desde hace meses y nunca había tenido un problema hasta ahora. Tenga en cuenta los 2 ingredientes necesarios para esta receta:

  1. Diseñe su modelo de objetos con un enfoque de compatibilidad con versiones anteriores, es decir, desaprobar objetos y atributos en lugar de eliminarlos o modificarlos. Esto significa que si necesita cambiar el nombre de un objeto o atributo, deje el antiguo como está, agregue el nuevo y escriba algún tipo de script de migración. Si necesita cambiar una asociación entre objetos, si ya está en producción, esto significa que su diseño fue incorrecto en primer lugar, así que trate de pensar en una nueva forma de express la nueva relación, sin afectar los datos antiguos.

  2. Haga siempre una copia de seguridad de la base de datos antes de la implementación.

Tengo la sensación, después de leer esta publicación, de que el 90% de las personas que participan en esta discusión están horrorizados solo con la idea de usar automatizaciones como esta en un entorno de producción. Algunos arrojan la pelota al DBA. Tómese un momento para considerar que no todos los entornos de producción proporcionarán un DBA y que muchos equipos de desarrollo no pueden pagarlo (al menos para proyectos de tamaño mediano). Entonces, si hablamos de equipos donde todos tienen que hacer todo, la pelota está sobre ellos.

En este caso, ¿por qué no tratar de tener lo mejor de ambos mundos? Herramientas como esta están aquí para ayudar, lo que, con un diseño y un plan cuidadosos, puede ayudar en muchas situaciones. Y créanme, los administradores pueden ser inicialmente difíciles de convencer, pero si saben que la pelota no está en sus manos, les encantará.

Personalmente, nunca volvería a escribir guiones a mano para extender cualquier tipo de esquema, pero esa es solo mi opinión. Y después de comenzar a adoptar las bases de datos sin esquema de NoSQL recientemente, puedo ver que más que pronto, todas estas operaciones basadas en esquemas pertenecerán al pasado, así que será mejor que comiences a cambiar tu perspectiva y mirar hacia el futuro.

Como expliqué en este artículo , no es una buena idea usar hbm2ddl.auto en producción.

La única forma de administrar el esquema de la base de datos es usar scripts de migración incremental porque:

  • los scripts residirán en VCS a lo largo de su código base. Cuando finaliza la compra de una sucursal, recrea el esquema completo desde cero.
  • los scripts incrementales se pueden probar en un servidor QA antes de ser aplicados en producción
  • no hay necesidad de intervención manual ya que los scripts pueden ser ejecutados por Flyway , por lo tanto, reduce la posibilidad de errores humanos asociados con la ejecución de scripts manualmente.

Incluso la Guía del usuario de Hibernate le aconseja evitar el uso de la herramienta hbm2ddl para entornos de producción.

enter image description here

No me arriesgaría porque podrías terminar perdiendo datos que deberían haberse conservado. hbm2ddl.auto = update es una forma puramente sencilla de mantener su base de datos de desarrollo actualizada.

  • En mi caso (Hibernate 3.5.2, Postgresql, Ubuntu), establecer hibernate.hbm2ddl.auto=update solo creaba nuevas tablas y creaba nuevas columnas en tablas ya existentes.

  • No soltó tablas, ni colocó columnas, ni alteró columnas. Se puede llamar una opción segura, pero algo como hibernate.hbm2ddl.auto=create_tables add_columns sería más claro.

No, nunca lo hagas. Hibernate no maneja la migración de datos. Sí, hará que su esquema se vea correctamente, pero no garantiza que los datos de producción valiosos no se pierdan en el proceso.

No es seguro, no es recomendable, pero es posible.

Tengo experiencia en una aplicación que usa la opción de actualización automática en producción.

Bueno, los principales problemas y riesgos encontrados en esta solución son:

  • Implementar en la base de datos incorrecta . Si comete un error al ejecutar el servidor de aplicaciones con una versión anterior de la aplicación (EAR / WAR / etc) en la base de datos incorrecta … Tendrá muchas columnas nuevas, tablas, claves foráneas y errores. El mismo problema puede ocurrir con un simple error en el archivo de fuente de datos, (copiar / pegar archivo y se olvidó de cambiar la base de datos). En resumen, la situación puede ser un desastre en su base de datos.
  • El servidor de aplicaciones tarda demasiado en comenzar . Esto ocurre porque el Hibernate intenta encontrar todas las tablas / columnas / etc creadas cada vez que inicia la aplicación. Él hace esto para saber qué (tabla, columna, etc.) necesita ser creado. Este problema solo empeorará.
  • Herramientas de base de datos es casi imposible de usar . Para crear scripts para la base de datos, debe pensar en lo que creará la actualización automática después de iniciar el servidor de aplicaciones. Si necesita completar una nueva columna (por ejemplo) con algunos datos, debe iniciar el servidor de la aplicación, esperar a Hibernate para crear la nueva columna y ejecutar el script SQL después de eso. Herramientas como Flyway es casi imposible de usar con la actualización automática habilitada.
  • Los cambios en la base de datos no están centralizados . Con la posibilidad de que Hibernate cree las tablas y todo lo demás, es difícil ver los cambios en la base de datos en cada versión de la aplicación, porque la mayoría de ellos son automáticos.
  • Alienta la basura en la base de datos . Debido a la facilidad de la actualización automática, existe la posibilidad de que su equipo descuide la posibilidad de eliminar columnas antiguas y tablas antiguas.
  • Desastre inminente El riesgo inminente de que ocurra algún desastre en la producción (como algunas personas mencionaron en otras respuestas). Incluso con una aplicación en ejecución y actualizable por años, no creo que sea seguro. Nunca me sentí seguro.

Por lo tanto, no recomendaré usar la actualización automática en producción.

Si realmente quieres usar la actualización automática en producción, te recomiendo:

  • Redes separadas Su entorno de prueba no puede acceder al entorno de homólogos. Esto ayuda a evitar que una implementación que se supone que debe estar en el entorno de prueba cambie la base de datos de homologación.
  • Gestionar orden de guiones . Debe organizar las secuencias de comandos para que se ejecuten antes de la implementación (cambio de tabla de estructura, colocar tabla / columnas) y secuencia de comandos después de la implementación (información de relleno para las nuevas columnas / tablas).

Y, a diferencia de las otras publicaciones, no creo que la actualización automática esté relacionada con los DBA “muy bien pagados” (como se menciona en otras publicaciones) … Los DBA tienen cosas más importantes que hacer que escribir sentencias de SQL para crear / cambiar / eliminar tablas y columnas. Estas simples tareas cotidianas pueden ser realizadas y automatizadas por los desarrolladores y solo pasan para que el equipo de DBA las revise, sin necesidad de que Hibernate y DBAs “muy bien pagados” los escriban.

  • Normalmente, las aplicaciones empresariales en grandes organizaciones se ejecutan con privilegios reducidos.

  • El nombre de usuario de la base de datos puede no tener el privilegio DDL para agregar columnas que hbm2ddl.auto=update requiere.

Estoy de acuerdo con Vladimir. Los administradores de mi empresa definitivamente no lo apreciarían si incluso sugerí tal curso.

Además, la creación de un script SQL en lugar de confiar ciegamente en Hibernate le brinda la oportunidad de eliminar campos que ya no están en uso. Hibernate no hace eso.

Y encuentro que comparar el esquema de producción con el nuevo esquema le da una mejor idea de lo que cambió en el modelo de datos. Ya sabes, por supuesto, porque lo hiciste, pero ahora ves todos los cambios de una vez. Incluso los que te hacen decir “¡¿Qué diablos ?!”.

Hay herramientas que pueden hacer un delta de esquema para usted, por lo que no es ni siquiera un trabajo duro. Y luego sabes exactamente lo que va a pasar.

El esquema de las aplicaciones puede evolucionar en el tiempo; si tiene varias instalaciones, que pueden tener diferentes versiones, debe asegurarse de que su aplicación, algún tipo de herramienta o secuencia de comandos, pueda migrar el esquema y los datos de una versión paso a paso a la siguiente.

Tener toda tu persistencia en las asignaciones (o anotaciones) de Hibernate es una muy buena manera de mantener la evolución del esquema bajo control.

Debe considerar que la evolución del esquema tiene varios aspectos a considerar:

  1. evolución del esquema de la base de datos al agregar más columnas y tablas

  2. caída de viejas columnas, tablas y relaciones

  3. llenar nuevas columnas con valores predeterminados

Las herramientas de Hibernate son importantes en particular en el caso (como en mi experiencia) tiene diferentes versiones de la misma aplicación en muchos tipos diferentes de bases de datos.

El punto 3 es muy sensible en caso de que esté utilizando Hibernate, como en el caso de que introduzca una nueva propiedad con valor booleano o una numérica, si Hibernate encuentra algún valor nulo en tales columnas, si genera una excepción.

Entonces, lo que haría es: utilizar la capacidad de las herramientas de Hibernate de actualización de esquema, pero debe agregar al mismo algunos datos y callback de mantenimiento de esquema, como para rellenar los valores predeterminados, descartar columnas que ya no se usan y similares. De esta manera, obtiene las ventajas (scripts de actualización de esquema independientes de la base de datos y evitar la encoding duplicada de las actualizaciones, en la persistencia y en los scripts), pero también cubre todos los aspectos de la operación.

Entonces, por ejemplo, si la actualización de una versión consiste simplemente en agregar una propiedad valorada en varchar (por lo tanto, columna), que puede ser nula de forma predeterminada, con la actualización automática habrá terminado. Donde se necesita más complejidad, se necesitará más trabajo.

Esto supone que la aplicación, cuando se actualiza, puede actualizar su esquema (se puede hacer), lo que también significa que debe tener los derechos de usuario para hacerlo en el esquema. Si la política del cliente previene este (caso probable de Lizard Brain), tendrá que proporcionar las secuencias de comandos específicas de la base de datos.