¿Está bien ejecutar aplicaciones de Hibernate configuradas hbm2ddl.auto=update
para actualizar el esquema de la base de datos en un entorno de producción?
¿Está bien ejecutar aplicaciones de Hibernate configuradas hbm2ddl.auto=update
para actualizar el esquema de la base de datos en un entorno de producción?
Respuestas:
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 hbm2ddl funcionó en desarrollo, también debería funcionar en producción. Pero en realidad, no siempre es el caso.
Incluso si funcionó bien, puede ser subóptimo. Los DBA se pagan tanto 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 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 en clúster, es posible que desee evitarlo porque pueden aparecer varias aplicaciones al mismo tiempo e intentar modificar el esquema que podría ser malo. O coloque algún mecanismo en el que solo una instancia pueda actualizar el esquema.
Los creadores de Hibernate desalientan hacerlo en un entorno de producción en su libro "Java Persistence with Hibernate" :
ADVERTENCIA: Hemos visto a usuarios de Hibernate tratando de usar 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á.
Consulte 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 que el control de revisión de DB / migración / gestión de cambios es muy infalible. Trabajo en un proyecto Groovy / Grails, y Grails usa Hibernate debajo de todo su ORM (llamado "GORM"). Usamos Liquibase para administrar todos los cambios en el esquema SQL, lo cual hacemos con bastante frecuencia a medida que nuestra aplicación evoluciona con nuevas características.
Básicamente, mantiene un archivo XML de conjuntos de cambios que continúa agregando a medida que su aplicación evoluciona. Este archivo se mantiene en git (o lo que sea que esté usando) con el resto de su proyecto. Cuando se implementa su aplicación, Liquibase verifica su tabla de registro de cambios en la base de datos a la que se está conectando para que sepa lo que ya se ha aplicado, luego 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 sus cambios de esquema, puede estar 100% seguro de que el código que extrae y despliega 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, 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 primero a un dev local o a un db provisional.
La manera más fácil de comenzar probablemente sería tomar su base de datos existente y luego usar Liquibase para generar un archivo baseline.xml inicial. Luego, en el futuro, puede agregarlo y dejar que liquibase se haga cargo de la administración de los cambios de esquema.
hbm2ddl.auto=update
para que sus asignaciones de Clase / DB estén validadas y tenga un control completo de la creación de DB a través de liquibase. ¿Qué piensas?
validate
Yo votaría no. Hibernate no parece entender cuándo los tipos de datos para 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 también hay otros ejemplos, como subir la longitud de una columna de cadena por encima de 255 y ver que se convierte a texto, texto medio, etc.
De acuerdo, no creo que haya realmente una manera de "convertir tipos de datos" sin crear una nueva columna, copiar los datos y eliminar la columna anterior. Pero en el momento en que su base de datos tiene columnas que no reflejan el mapeo actual de Hibernate, está viviendo de manera muy peligrosa ...
Flyway es una buena opción para tratar este problema:
@Column(length = 45)
a @Column(length = 255)
. Puede verificar que Hibernate 4.3.6.Final actualizó correctamente el esquema de la base de datos utilizando hbm2ddl.auto=update
. (Una cosa para mencionar es que la base de datos actualmente no tiene ningún dato, solo la estructura)
Hibernate tiene que poner el descargo de responsabilidad sobre no usar actualizaciones automáticas en productos para cubrirse cuando las personas que no saben lo que están haciendo lo usan en situaciones en las que no deberían usarse.
Por supuesto, las situaciones en las que no debe usarse superan en gran medida las situaciones en las que está bien.
Lo he usado durante años en muchos proyectos diferentes y nunca he tenido un solo problema. Esa no es una respuesta tonta, y no es una codificación de vaquero. Es un hecho histórico.
Una persona que dice "nunca lo hagas en producción" está pensando en un conjunto específico de despliegues de producción, a saber, 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 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.), está bien.
Cuando agrega muchas funciones, las actualizaciones automáticas de esquemas pueden ahorrarle 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, agregar columnas no anulables, cambios de nombre de columna, etc.
También debe tener cuidado en entornos agrupados.
Pero, de nuevo, si supieras todo esto, no harías esta pregunta. Hmm . . OK, si está haciendo esta pregunta, debe esperar hasta tener mucha experiencia con Hibernate y las actualizaciones de esquemas automáticos antes de pensar en usarlo en prod.
Como expliqué en este artículo , no es una buena idea usarlo 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:
Incluso la Guía del usuario de Hibernate le aconseja que evite usar la hbm2ddl
herramienta para entornos de producción.
SchemaExport
como lo demuestra este caso de prueba .
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, que es despreciar los objetos y atributos en lugar de eliminarlos / alterarlos. 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 estaba equivocado en primer lugar, así que trate de 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 sensación es, después de leer esta publicación, que el 90% de las personas que participan en esta discusión están horrorizadas solo con la idea de usar automatizaciones como esta en un entorno de producción. Algunos lanzan la pelota al DBA. Tómese un momento para considerar que no todos los entornos de producción proporcionarán un DBA y que no muchos equipos de desarrollo pueden permitirse uno (al menos para proyectos de tamaño mediano). Entonces, si estamos hablando 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 difíciles de convencer inicialmente, pero si saben que la pelota no está en sus manos, les encantará.
Personalmente, nunca volvería a escribir guiones a mano para extender ningún tipo de esquema, pero esa es solo mi opinión. Y después de comenzar a adoptar bases de datos sin esquema NoSQL recientemente, puedo ver que más que pronto, todas estas operaciones basadas en esquemas pertenecerán al pasado, por lo que será mejor que comience a cambiar su perspectiva y mirar hacia el futuro.
No me arriesgaría porque podría terminar perdiendo datos que deberían haberse conservado. hbm2ddl.auto = update es puramente una manera fácil de mantener actualizada su base de datos de desarrollo.
En mi caso (Hibernate 3.5.2, Postgresql, Ubuntu), la configuración hibernate.hbm2ddl.auto=update
solo creó nuevas tablas y creó nuevas columnas en tablas ya existentes.
No soltó tablas, ni soltó columnas, ni alteró columnas. Puede llamarse una opción segura, pero algo así hibernate.hbm2ddl.auto=create_tables add_columns
sería más claro.
No es seguro, no se recomienda, 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:
Por lo tanto, no recomendaré usar la actualización automática en producción.
Si realmente desea utilizar la actualización automática en producción, le recomiendo:
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 menciona en otras publicaciones). Los DBA tienen cosas más importantes que hacer que escribir declaraciones SQL para crear / cambiar / eliminar tablas y columnas. Los desarrolladores pueden realizar y automatizar estas sencillas tareas cotidianas y solo se pueden aprobar para que el equipo del DBA las revise, sin necesidad de que Hibernate y los DBA estén "muy bien pagados" para escribirlas.
Por lo general, las aplicaciones empresariales en grandes organizaciones se ejecutan con privilegios reducidos.
El nombre de usuario de la base de datos puede no tener DDL
privilegios para agregar columnas, lo que hbm2ddl.auto=update
requiere.
Estoy de acuerdo con Vladimir. Los administradores de mi empresa definitivamente no lo apreciarían si 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 se usan. Hibernate no hace eso.
Y encuentro que comparar el esquema de producción con el nuevo esquema te da una mejor perspectiva de lo que has cambiado 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 esquema delta para usted, por lo que ni siquiera es un trabajo duro. Y luego sabes exactamente lo que va a pasar.
El esquema de las aplicaciones puede evolucionar con 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 esquemas y datos de una versión paso a paso a cualquiera.
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.
Debe 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 viejas columnas, tablas y relaciones
llenar nuevas columnas con valores predeterminados
Las herramientas de Hibernate son importantes en particular en caso de que (como en mi experiencia) tenga 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, ya que si introduce una nueva propiedad con valor booleano o una numérica, si Hibernate encuentra algún valor nulo en dichas columnas, si se produce una excepción.
Entonces, lo que haría es: de hecho, use la capacidad de las herramientas de Hibernate para la actualización del esquema, pero debe agregar junto con ella algunos datos y devolución de llamada de mantenimiento del esquema, como para completar valores predeterminados, descartar columnas que ya no se usan y similares. De esta forma, obtiene las ventajas (guiones de actualización de esquemas independientes de la base de datos y evita la codificación duplicada de las actualizaciones, en persistencia y en guiones), 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 con valor varchar (por lo tanto, columna), que puede ser nula de forma predeterminada, con la actualización automática, habrá terminado. Donde más complejidad es necesaria, más trabajo será necesario.
Esto 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 (probablemente en el caso de Lizard Brain), deberá proporcionar los scripts específicos de la base de datos.