java - order_updates - Hibernate: hbm2ddl.auto=¿actualización en producción?
jpa auto create (15)
¿Es correcto ejecutar aplicaciones de Hibernate configuradas con hbm2ddl.auto=update
para actualizar el esquema de la base de datos en un entorno de producción?
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 incrementales porque:
- Los scripts residirán en VCS a lo largo de su base de código. Cuando selecciona una rama, vuelve a crear todo el esquema desde cero.
- Los scripts incrementales pueden probarse en un servidor de control de calidad 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 manual de los scripts.
Incluso la Guía del usuario de Hibernate aconseja evitar el uso de la herramienta hbm2ddl
para entornos de producción.
Echa un vistazo a LiquiBase XML para mantener un registro de cambios de actualizaciones. Nunca lo había usado hasta este año, pero descubrí que es muy fácil de aprender y hacer que el control de revisión / migración / gestión de cambios de DB sea infalible. Trabajo en un proyecto Groovy / Grails, y Grails usa Hibernate debajo de todo su ORM (llamado "GORM"). Utilizamos Liquibase para administrar todos los cambios del esquema SQL, lo que hacemos con bastante frecuencia a medida que nuestra aplicación evoluciona con nuevas características.
Básicamente, mantienes un archivo XML de conjuntos de cambios que continúas agregando a medida que tu aplicación evoluciona. Este archivo se guarda en git (o lo que esté usando) con el resto de su proyecto. Cuando se implementa su aplicación, Liquibase comprueba su tabla de cambios en la base de datos a la que se está conectando para que sepa lo que ya se ha aplicado, luego se aplica de manera inteligente cualquier conjunto de cambios que aún no se haya aplicado desde el archivo. Funciona absolutamente bien en la práctica, y si lo usa para todos los cambios de esquema, entonces puede estar 100% seguro de que el código que extraiga y despliegue siempre podrá conectarse a un esquema de base de datos totalmente compatible.
Lo sorprendente es que puedo tomar una base de datos mysql de pizarra totalmente en blanco en mi computadora portátil, encender la aplicación y, de inmediato, el esquema está configurado para mí. También facilita la prueba de los cambios de esquema aplicándolos primero a un db local o de desarrollo.
La forma más fácil de comenzar con él probablemente sería tomar su base de datos existente y luego usar Liquibase para generar un archivo inicial baseline.xml. Luego, en el futuro, simplemente puede agregarlo y dejar que liquibase se haga cargo de la gestión de los cambios de esquema.
El esquema de las aplicaciones puede evolucionar en el tiempo; Si tiene varias instalaciones, que pueden estar en diferentes versiones, debe tener alguna forma de asegurarse de que su aplicación, algún tipo de herramienta o script sea capaz de migrar el esquema y los datos de una versión paso a paso a la siguiente.
Tener toda su persistencia en las asignaciones (o anotaciones) de Hibernate es una muy buena manera de mantener bajo control la evolución del esquema.
Debes considerar que la evolución del esquema tiene varios aspectos a considerar:
Evolución del esquema de la base de datos al agregar más columnas y tablas.
Caída de columnas antiguas, tablas y relaciones.
Rellenar nuevas columnas con valores por defecto.
Las herramientas de Hibernate son importantes en particular en el caso (como en mi experiencia) tiene diferentes versiones de la misma aplicación en diferentes tipos de bases de datos.
El punto 3 es muy sensible en caso de que esté usando Hibernate, ya que en caso de que introduzca una nueva propiedad con valor booleano o numérica, si Hibernate encontrará algún valor nulo en dichas columnas, si genera una excepción.
Entonces, lo que haría sería: utilizar la capacidad de actualización de esquemas de las herramientas de Hibernate, pero debe agregar junto con algunos datos y devolución de llamada de mantenimiento de esquemas, como rellenar los valores predeterminados, eliminar las columnas que ya no se utilizan y similares. De este modo, obtiene las ventajas (scripts de actualización de esquemas independientes de la base de datos y evitación de la codificación duplicada de las actualizaciones, tanto en peristence como en scripts), pero también cubre todos los aspectos de la operación.
Entonces, por ejemplo, si una actualización de versión consiste simplemente en agregar una propiedad de valor varchar (por lo tanto, columna), que puede ser nula por defecto, con la actualización automática estará listo. Donde sea necesaria más complejidad, será necesario más trabajo.
Esto se supone que la aplicación, cuando se actualiza, es capaz de 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 lo impide (caso probable de Lizard Brain), deberá proporcionar los scripts específicos de la base de datos.
Estoy de acuerdo con Vladimir. Los administradores de mi empresa definitivamente no lo apreciarían si yo incluso sugiriera tal curso.
Además, crear 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 me parece que comparar el esquema de producción con el nuevo esquema le brinda una mejor perspectiva de cómo cambió el modelo de datos. Usted sabe, por supuesto, porque lo hizo, pero ahora ve todos los cambios de una sola vez. Incluso los que te hacen ir como "¡¿Qué diablos ?!".
Hay herramientas que pueden hacer un delta de esquema para usted, por lo que ni siquiera es un trabajo duro. Y entonces sabes exactamente lo que va a pasar.
Hibernate tiene que poner el descargo de responsabilidad acerca de no usar actualizaciones automáticas en prod para cubrirse a sí mismos cuando las personas que no saben lo que están haciendo lo usan en situaciones donde no se debe usar.
Concedidas las situaciones en las que no se debe utilizar superan en gran medida a 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 aburrida, y no es codificación de vaquero. Es un hecho histórico.
Una persona que dice "nunca lo haga en producción" está pensando en un conjunto específico de implementaciones de producción, a saber, con las 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 va a resultar de una configuración de mapeo dada. Siempre que pruebe y valide que lo que espera termina en el DDL (en dev, qa, puesta en escena, etc.), estará bien.
Cuando agrega muchas funciones, las actualizaciones automáticas de esquemas pueden ser un ahorro de tiempo real.
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 no anulables, los cambios de nombre de columna, etc., etc.
También es necesario tener cuidado en entornos agrupados.
Pero, de nuevo, si supieras todo esto, no estarías haciendo esta pregunta. Hmm . . De acuerdo, si está haciendo esta pregunta, debe esperar hasta que tenga mucha experiencia con las actualizaciones de Hibernate y el esquema automático antes de pensar en usarlo en prod.
Lo hacemos en producción, aunque con una aplicación que no es de misión crítica y que no cuenta con DBA altamente pagados en el personal. Es solo un proceso menos manual que está sujeto a errores humanos: la aplicación puede detectar la diferencia y hacer lo correcto, además de que probablemente lo haya probado en varios entornos de desarrollo y prueba.
Una advertencia: en un entorno agrupado, es posible que desee evitarlo, ya que pueden surgir varias aplicaciones al mismo tiempo e intentar modificar el esquema, lo que podría ser incorrecto. O ponga algún mecanismo donde solo una instancia tenga permiso para actualizar el esquema.
Lo hacemos en un proyecto que se ejecuta en producción desde hace meses y nunca tuvimos un problema hasta ahora. Tenga en cuenta los 2 ingredientes necesarios para esta receta:
Diseñe su modelo de objetos con un enfoque de compatibilidad con versiones anteriores, es decir, desapruebe objetos y atributos en lugar de eliminarlos / alterarlos. Esto significa que si necesita cambiar el nombre de un objeto o atributo, deje el anterior tal 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 intente pensar en una nueva forma de expresar la nueva relación, sin afectar los datos antiguos.
Siempre haga una copia de seguridad de la base de datos antes de la implementación.
Mi opinión es, después de leer este post, que el 90% de las personas que participan en esta discusión están horrorizados solo con la idea de utilizar automatizaciones como esta en un entorno de producción. Algunos tiran la pelota al DBA. Sin embargo, tómese un momento para considerar que no todos los entornos de producción proporcionarán un DBA y no muchos equipos de desarrollo podrán costear uno (al menos para proyectos de tamaño medio). Entonces, si estamos hablando de equipos donde todos tienen que hacer todo, la pelota está en ellos.
En este caso, ¿por qué no tratar de tener lo mejor de ambos mundos? Herramientas como esta están aquí para ayudar, que, con un diseño y un plan cuidadosos, pueden ayudar en muchas situaciones. Y créanme, inicialmente los administradores pueden ser 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 ampliar cualquier tipo de esquema, pero esa es solo mi opinión. Y luego de comenzar a adoptar las bases de datos sin esquema NoSQL recientemente, puedo ver que más pronto, todas estas operaciones basadas en esquemas pertenecerán al pasado, por lo que es mejor que empieces a cambiar tu perspectiva y mires hacia adelante.
Los creadores de Hibernate no recomiendan hacerlo en un entorno de producción en su libro "Persistencia de Java con Hibernate" :
ADVERTENCIA: los usuarios de Hibernate han intentado utilizar SchemaUpdate para actualizar el esquema de una base de datos de producción automáticamente. Esto puede terminar rápidamente en un desastre y su DBA no lo permitirá.
No es seguro, no es recomendable, pero es posible.
Tengo experiencia en una aplicación utilizando 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 el error de 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, tablas, claves externas y errores nuevos. El mismo problema puede ocurrir con un simple error en el archivo de fuente de datos, (copiar / pegar archivo y olvidó 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 iniciarse . Esto ocurre porque Hibernate intenta encontrar todas las tablas / columnas / etc creadas cada vez que inicia la aplicación. Hace esto para saber qué (tabla, columna, etc.) se necesita crear. 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 se creará con la actualización automática después de iniciar el servidor de aplicaciones. Si necesita rellenar una nueva columna (por ejemplo) con algunos datos, necesita iniciar el servidor de aplicaciones, esperar a que Hibernate cree 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 observar los cambios en la base de datos en cada versión de la aplicación, ya que 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 deje de colocar columnas y tablas antiguas.
- Desastre inminente El riesgo inminente de que ocurra algún desastre en la producción (como algunas personas mencionadas en otras respuestas). Incluso con una aplicación en ejecución y actualizable durante años, no creo que sea segura. Nunca me sentí segura.
Por lo tanto, no recomendaré utilizar la actualización automática en la producción.
Si realmente desea utilizar la actualización automática en producción, le recomiendo:
- Redes separadas . Su entorno de prueba no puede acceder al entorno homólogo. Esto ayuda a evitar que una implementación que debía estar en el entorno de prueba cambie la base de datos de homologación.
- Gestionar el orden de los scripts . Debe organizar sus secuencias de comandos para que se ejecuten antes de su implementación (cambio de la estructura de la tabla, eliminar tablas / columnas) y la secuencia de comandos después de la implementación (completar la información de las nuevas columnas / tablas).
Y, a diferencia de las otras publicaciones, no creo que la actualización automática habilitada esté relacionada con DBA "muy bien pagados" (como se mencionó en otras publicaciones) ... Los DBA tienen cosas más importantes que hacer que escribir sentencias de SQL para crear / cambiar / borrar tablas y columnas. Los desarrolladores pueden hacer estas tareas cotidianas simples y automatizadas, y solo las pasan para que el equipo de DBA las revise, ya que no es necesario que Hibernate y DBA estén "bien pagados" para escribirlas.
No me arriesgaría porque podría terminar perdiendo datos que deberían haberse conservado. hbm2ddl.auto = actualizar es puramente una forma fácil de mantener su base de datos dev actualizada.
No, es inseguro.
A pesar de los mejores esfuerzos del equipo de Hibernate, simplemente no puede confiar en las actualizaciones automáticas en la 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. DBAs se pagan mucho por una razón.
No, nunca lo hagas. Hibernate no maneja la migración de datos. Sí, hará que su esquema se vea correctamente, pero no garantiza que no se pierdan datos de producción valiosos en el proceso.
Yo votaría no. Hibernate no parece entender cuando los tipos de datos de las columnas han cambiado. 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 hay otros ejemplos también, como subir la longitud de una columna de Cadena a más de 255 y verla convertir a texto, texto medio, etc.
Por supuesto, no creo que realmente haya una manera de "convertir tipos de datos" sin crear una nueva columna, copiar los datos y eliminar la columna anterior. Pero el minuto en que su base de datos tiene columnas que no reflejan el mapa actual de Hibernate en el que vive, es muy peligroso ...
Flyway es una buena opción para hacer frente a este problema:
En mi caso (Hibernate 3.5.2, Postgresql, Ubuntu), la configuración de
hibernate.hbm2ddl.auto=update
solo creó tablas nuevas y columnas nuevas en tablas ya existentes.No eliminó tablas, ni eliminó columnas, ni alteró columnas. Puede llamarse una opción segura, pero algo como
hibernate.hbm2ddl.auto=create_tables add_columns
sería más claro.
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 requierehbm2ddl.auto=update
.