Hibernate: hbm2ddl.auto = atualização em produção?

338

Posso executar aplicativos do Hibernate configurados hbm2ddl.auto=updatepara atualizar o esquema do banco de dados em um ambiente de produção?

Cretzel
fonte
6
Nós fazemos. Nunca tive problemas.
Cretzel # 21/08
4
Muito boa pergunta. Eu enfrento isso agora. Então agora 2018 - após 10 anos, qual é a sua opinião? É seguro usar a atualização do Hibernate em bancos de dados de produção de clientes importantes com esquemas complexos?
precisa

Respostas:

388

Não, é inseguro.

Apesar dos melhores esforços da equipe do Hibernate, você simplesmente não pode contar com atualizações automáticas na produção . Escreva seus próprios patches, revise-os com o DBA, teste-os e aplique-os manualmente.

Teoricamente, se o hbm2ddl update funcionou no desenvolvimento, também deveria funcionar na produção. Mas, na realidade, nem sempre é o caso.

Mesmo se funcionou bem, pode ser abaixo do ideal. Os DBAs são pagos por um motivo.

Vladimir Dyuzhev
fonte
33
Por que é inseguro?
cretzel
74
É inseguro porque os patches aplicados podem ter efeitos colaterais que o hbm2ddl dificilmente pode prever (como desativar os acionadores que foram instalados para a modificação da tabela). Para esquemas complexos, a maneira mais segura é manual. O teste automático com pós-regressão é o segundo distante. Todos IMHO.
Vladimir Dyuzhev 21/10/08
18
A atualização de um esquema db também deve ser tratada pelos profissionais (dbas). Recuperar de uma alteração ruim de banco de dados é difícil, na melhor das hipóteses. Vova não mencionou - mas o que acontece se a atualização do hibernate decide soltar uma coluna e adicioná-la novamente porque o tipo ou tamanho mudou. Digamos que a coluna seja todos os endereços de e-mail dos seus usuários? :-) adeus, empresa de despedida ... Você deseja que a alteração do DDL seja gerada automaticamente - mas você deseja que a alteração seja inspecionada por um ser humano.
Pat
9
você não faz backup de seus bancos de dados antes de uma atualização?
Jacob
21
No momento, a atualização do esquema do Hibernate não descarta tabelas ou colunas.
Brian Deterling
70

Fazemos isso em produção, embora com um aplicativo que não é essencial e sem DBAs altamente pagos na equipe. É apenas um processo manual a menos que está sujeito a erro humano - o aplicativo pode detectar a diferença e fazer a coisa certa, além de que você provavelmente já o testou em vários ambientes de desenvolvimento e teste.

Uma ressalva - em um ambiente em cluster, convém evitá-lo porque vários aplicativos podem surgir ao mesmo tempo e tentar modificar o esquema que pode ser ruim. Ou coloque algum mecanismo em que apenas uma instância tenha permissão para atualizar o esquema.

Brian Deterling
fonte
2
Também o usamos em Produção, caso de uso semelhante. Plataforma de análise que não é essencial. Implementamos 16K vezes em 4 ambientes (4 anos) sem muito soluço com o hibernação. Somos uma equipe pequena e somos todos iniciantes em SQL RDBS e temos mais fé no esquema de manipulação do Hibernate do que nós mesmos. Gostaria de saber qual é a taxa de erro para ter um DBA na equipe que gerencia migrações e alterações de esquema? É melhor que 0 em ~ 16K implantações?
user3263752
O que você diria abour este comentário por pat? stackoverflow.com/questions/221379/…
Shiva kumar,
52

Os criadores do Hibernate desencorajam isso em um ambiente de produção em seu livro "Java Persistence with Hibernate" :

AVISO: Vimos usuários do Hibernate tentando usar o SchemaUpdate para atualizar o esquema de um banco de dados de produção automaticamente. Isso pode terminar rapidamente em desastre e não será permitido pelo seu DBA.

romano
fonte
11
Isso foi escrito em 2006?
user3263752
28

Confira o XML do LiquiBase para manter um registro de alterações. Eu nunca o havia usado até este ano, mas achei muito fácil aprender e tornar o controle de revisão de banco de dados / migração / gerenciamento de alterações muito infalível. Eu trabalho em um projeto Groovy / Grails, e o Grails usa o Hibernate abaixo de todo o seu ORM (chamado "GORM"). Usamos o Liquibase para gerenciar todas as alterações de esquema SQL, o que fazemos com bastante frequência à medida que nosso aplicativo evolui com novos recursos.

Basicamente, você mantém um arquivo XML de conjuntos de alterações aos quais continua adicionando à medida que seu aplicativo evolui. Este arquivo é mantido no git (ou o que você estiver usando) com o restante do seu projeto. Quando seu aplicativo é implantado, o Liquibase verifica a tabela de registro de alterações no banco de dados ao qual você está se conectando, para saber o que já foi aplicado e, de maneira inteligente, aplica apenas quaisquer conjuntos de alterações que ainda não foram aplicados no arquivo. Na prática, ele funciona muito bem e, se você o usar para todas as alterações de esquema, poderá estar 100% confiante de que o código que você faz o checkout e implanta sempre poderá se conectar a um esquema de banco de dados totalmente compatível.

O mais impressionante é que posso pegar um banco de dados mysql em branco no meu laptop, iniciar o aplicativo e imediatamente o esquema está configurado para mim. Também facilita o teste de alterações de esquema, aplicando-as a um local-dev ou banco de dados de teste primeiro.

A maneira mais fácil de começar provavelmente seria usar o banco de dados existente e usar o Liquibase para gerar um arquivo baseline.xml inicial. No futuro, você pode simplesmente anexá-lo e deixar o liquibase assumir o gerenciamento das alterações de esquema.

http://www.liquibase.org/

jpswain
fonte
Perfeito, exatamente para o que eu estava prestes a mudar. Eu sinto a melhor coisa, dar um passo adiante seria adicionar hbm2ddl.auto=updatepara que seus mapeamentos de Class / DB sejam validados e você tenha controle completo da criação do DB por meio do liquibase. O que você acha?
precisa saber é o seguinte
Opa, eu quis dizervalidate
bholagabbar 8/17/17
O liquibase é melhor no gerenciamento de scripts usando "include-import", como suporte e suporte a controle de versão e atributo "Type" para arquivos, o que ajuda a ter diferentes arquivos SQL para diferentes ambientes com relacionamento pai-filho. em poucas palavras, escolha o tradicional SQL Mgmt. em produção. Para o desenvolvimento, precisamos de velocidade para produção, precisamos de garantias, estabilidade e backup.
precisa
26

Eu votaria não. O Hibernate parece não entender quando os tipos de dados das colunas foram alterados. Exemplos (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

Provavelmente também existem outros exemplos, como aumentar o comprimento de uma coluna String para mais de 255 e vê-la converter em texto, texto médio, etc.

É verdade que não acho que exista uma maneira de "converter tipos de dados" sem criar uma nova coluna, copiar os dados e remover a coluna antiga. Mas no minuto em que seu banco de dados possui colunas que não refletem o mapeamento atual do Hibernate, você está vivendo muito perigosamente ...

O Flyway é uma boa opção para lidar com esse problema:

http://flywaydb.org

cliff.meyers
fonte
11
Eu apenas tentei a primeira parte do seu exemplo - no meu caso, mude @Column(length = 45)para @Column(length = 255). Pode verificar se o Hibernate 4.3.6.Final atualizou corretamente o esquema do banco de dados usando hbm2ddl.auto=update. (Uma coisa a mencionar é o banco de dados não tem actualmente quaisquer dados nele -. Apenas a estrutura)
Steve Chambers
É bem possível que eles tenham corrigido esse bug em algum lugar nos últimos 6 anos ou mais. No entanto, se você teve dados no esquema e fez uma alteração que resultou em uma diminuição na largura da coluna, você encontrará erros ou truncamento de dados não gerenciados.
cliff.meyers
11
O flywaydb precisa de um script SQL criado manualmente, deve ser melhor do que um programa automático pode fazer, mas quem pode escrever um script grande, então é um problema.
B Rng Rikimaru
25

O Hibernate precisa exonerar-se de não usar as atualizações automáticas no prod para se cobrir quando as pessoas que não sabem o que estão fazendo o usam em situações em que não devem ser usadas.

As situações em que não devem ser usadas superam em muito as situações em que está OK.

Eu o uso há anos em muitos projetos diferentes e nunca tive um único problema. Essa não é uma resposta idiota, e não é uma codificação de cowboy. É um fato histórico.

Uma pessoa que diz "nunca faça isso na produção" está pensando em um conjunto específico de implantações de produção, a saber, aquelas com as quais está familiarizado (sua empresa, sua indústria, etc.).

O universo das "implantações de produção" é vasto e variado.

Um desenvolvedor experiente do Hibernate sabe exatamente o que o DDL resultará de uma determinada configuração de mapeamento. Contanto que você teste e valide que o que você espera acaba no DDL (em dev, qa, preparo etc.), você estará bem.

Quando você adiciona muitos recursos, as atualizações automáticas de esquema podem economizar tempo real.

A lista de atualizações automáticas que não serão tratadas é interminável, mas alguns exemplos são a migração de dados, a adição de colunas não anuláveis, alterações no nome da coluna, etc.

Além disso, você precisa tomar cuidado em ambientes em cluster.

Mas, novamente, se você soubesse tudo isso, não faria essa pergunta. Hmm . . . OK, se você está fazendo esta pergunta, deve esperar até ter muita experiência com o Hibernate e as atualizações automáticas de esquema antes de pensar em usá-lo no prod.

john.stein
fonte
19

Como expliquei neste artigo , não é uma boa ideia usar hbm2ddl.autona produção.

A única maneira de gerenciar o esquema do banco de dados é usar scripts de migração incremental porque:

  • os scripts residirão no VCS ao longo de sua base de código. Ao fazer o check-out de uma ramificação, você recriará todo o esquema do zero.
  • os scripts incrementais podem ser testados em um servidor de controle de qualidade antes de serem aplicados na produção
  • não há necessidade de intervenção manual, pois os scripts podem ser executados pelo Flyway ; portanto, reduz a possibilidade de erro humano associado à execução manual de scripts.

Até o Guia do Usuário do Hibernate recomenda evitar a utilização da hbm2ddlferramenta em ambientes de produção.

insira a descrição da imagem aqui

Vlad Mihalcea
fonte
Esta é uma resposta perfeita e concordo com ela. Mas realmente acho a idéia de criar o primeiro script de banco de dados manualmente pesado (ou seja, V1_0__initial_script.sql no caso do exemplo no link). Existe uma maneira de criar um script do meu banco de dados de desenvolvimento existente que o Hibernate criou para mim e armazenar no V1_0_intial_script.sql ??
precisa saber é o seguinte
11
Use SchemaExportconforme demonstrado neste caso de teste .
Vlad Mihalcea 26/01/19
Obrigado. Me deparei com um despejo de linha única "mysqldump -u root -p --no-data dbname> schema.sql". Existe alguma desvantagem em usar o dump gerado com isso?
HopeKing
11
Não há problema em usar um despejo de banco de dados.
Vlad Mihalcea 26/01/19
8

Fazemos isso em um projeto em execução há meses e nunca tivemos um problema até agora. Lembre-se dos 2 ingredientes necessários para esta receita:

  1. Projete seu modelo de objeto com uma abordagem de compatibilidade com versões anteriores, que substitui objetos e atributos em vez de removê-los / alterá-los. Isso significa que, se você precisar alterar o nome de um objeto ou atributo, deixe o antigo como está, adicione o novo e escreva algum tipo de script de migração. Se você precisar alterar uma associação entre objetos, se você já estiver em produção, isso significa que seu design estava errado em primeiro lugar; portanto, tente pensar em uma nova maneira de expressar o novo relacionamento, sem afetar os dados antigos.

  2. Sempre faça backup do banco de dados antes da implantação.

Meu senso é - depois de ler este post - que 90% das pessoas que participam dessa discussão ficam horrorizadas apenas com o pensamento de usar automações como essa em um ambiente de produção. Alguns jogam a bola no DBA. Reserve um momento para considerar que nem todos os ambientes de produção fornecem um DBA e poucas equipes de desenvolvimento podem pagar um (pelo menos para projetos de tamanho médio). Então, se estamos falando de equipes em que todos precisam fazer tudo, a bola está neles.

Nesse caso, por que não tentar ter o melhor dos dois mundos? Ferramentas como esta estão aqui para ajudar, as quais - com um design e plano cuidadosos - podem ajudar em muitas situações. E acredite, os administradores podem inicialmente ser difíceis de convencer, mas se souberem que a bola não está em suas mãos, eles vão adorar.

Pessoalmente, eu nunca voltaria a escrever scripts manualmente para estender qualquer tipo de esquema, mas essa é apenas a minha opinião. E depois de começar a adotar os bancos de dados NoSQL sem esquema recentemente, posso ver que, em breve, todas essas operações baseadas em esquema pertencerão ao passado, então é melhor começar a mudar sua perspectiva e olhar para frente.

chris
fonte
4
Discordo do comentário NoSQL. Definitivamente, está em ascensão e tem seu lugar, mas existem muitos aplicativos que dependem absolutamente da conformidade com o ACID para a integridade dos dados, com simultaneidade e transações que o NoSQL simplesmente não pode fornecer.
Jspwain 13/08
7

Eu não correria o risco, porque você pode acabar perdendo dados que deveriam ter sido preservados. hbm2ddl.auto = update é uma maneira fácil de manter seu banco de dados atualizado.

Jaap Coomans
fonte
2
você não faz backup de seus bancos de dados antes de uma atualização?
Jacob Jacob
6
Sim, claro que sim, mas é muito trabalhoso restaurar a partir de um backup. Não vale a pena o trabalho de restaurar backups quando você também pode atualizar seu banco de dados de maneira ordenada.
Jaap Coomans
6
  • No meu caso (Hibernate 3.5.2, Postgresql, Ubuntu), a configuração hibernate.hbm2ddl.auto=updatecriou apenas novas tabelas e criou novas colunas em tabelas já existentes.

  • Ele não eliminou tabelas, nem eliminou colunas, nem alterou colunas. Pode ser chamado de opção segura, mas algo como hibernate.hbm2ddl.auto=create_tables add_columnsseria mais claro.

user1027272
fonte
6

Não é seguro, não é recomendado, mas é possível.

Tenho experiência em um aplicativo usando a opção de atualização automática na produção.

Bem, os principais problemas e riscos encontrados nesta solução são:

  • Implantar no banco de dados errado . Se você cometer o erro de executar o servidor de aplicativos com uma versão antiga do aplicativo (EAR / WAR / etc) no banco de dados errado ... Você terá muitas novas colunas, tabelas, chaves estrangeiras e erros. O mesmo problema pode ocorrer com um simples erro no arquivo de fonte de dados (copiar / colar o arquivo e esqueceu de alterar o banco de dados). Em resumo, a situação pode ser um desastre no seu banco de dados.
  • O servidor de aplicativos leva muito tempo para iniciar . Isso ocorre porque o Hibernate tenta encontrar todas as tabelas / colunas / etc criadas sempre que você inicia o aplicativo. Ele precisa saber o que (tabela, coluna, etc) precisa ser criado. Esse problema só piora à medida que as tabelas do banco de dados crescem.
  • Ferramentas de banco de dados é quase impossível de usar . Para criar scripts DDL ou DML do banco de dados para executar com uma nova versão, é necessário pensar no que será criado pela atualização automática após o início do servidor de aplicativos. Por exemplo, se você precisar preencher uma nova coluna com alguns dados, inicie o servidor de aplicativos, aguarde até o Hibernate criar a nova coluna e execute o script SQL somente depois disso. Como você pode ver, as ferramentas de migração de banco de dados (como Flyway, Liquibase etc.) são quase impossíveis de usar com a atualização automática ativada.
  • As alterações no banco de dados não são centralizadas . Com a possibilidade do Hibernate criar tabelas e tudo mais, é difícil observar as alterações no banco de dados em cada versão do aplicativo, porque a maioria delas é feita automaticamente.
  • Incentiva o lixo no banco de dados . Por causa do uso "fácil" da atualização automática, há uma chance de sua equipe descartar colunas e tabelas antigas, porque a atualização automática de hibernação não pode fazer isso.
  • Desastre iminente . O risco iminente de algum desastre ocorrer na produção (como algumas pessoas mencionadas em outras respostas). Mesmo com um aplicativo em execução e sendo atualizado há anos, não acho que seja uma escolha segura. Nunca me senti seguro com essa opção sendo usada.

Portanto, não recomendamos o uso da atualização automática na produção.

Se você realmente deseja usar a atualização automática na produção, recomendo:

  • Redes separadas . Seu ambiente de teste não pode acessar o ambiente homólogo. Isso ajuda a impedir que uma implantação que deveria estar no ambiente de teste altere o banco de dados de Homologação.
  • Gerenciar a ordem dos scripts . Você precisa organizar seus scripts para execução antes da sua implantação (alteração da tabela de estrutura, descartar tabela / colunas) e script após a implantação (preencher informações para as novas colunas / tabelas).

E, diferente das outras postagens, acho que a atualização automática não está relacionada a DBAs "muito bem pagos" (como mencionado em outras postagens). Os DBAs têm coisas mais importantes a fazer do que escrever instruções SQL para criar / alterar / excluir tabelas e colunas. Essas tarefas simples do dia-a-dia podem ser executadas e automatizadas pelos desenvolvedores e passadas apenas para a equipe do DBA revisar, não necessitando de Hibernate e DBAs "muito bem pagos" para escrevê-los.

Dherik
fonte
4

Não, nunca faça isso. O Hibernate não lida com a migração de dados. Sim, ele fará com que seu esquema seja exibido corretamente, mas não garante que dados valiosos de produção não sejam perdidos no processo.

Robert
fonte
4
  • Normalmente, aplicativos corporativos em grandes organizações são executados com privilégios reduzidos.

  • O nome de usuário do banco de dados pode não ter DDLprivilégio para adicionar colunas hbm2ddl.auto=updatenecessárias.

Aniket Kulkarni
fonte
esse é um problema que frequentemente encontro. Tentamos usar o hibernate para a criação inicial do banco de dados, mas geralmente não é possível fazer isso.
Dan
5
Não é um "problema", é uma coisa certa.
Vladimir Dyuzhev 25/03
2

Eu concordo com o Vladimir. Os administradores da minha empresa definitivamente não apreciariam se eu sugerisse esse curso.

Além disso, a criação de um script SQL em vez de confiar cegamente no Hibernate oferece a oportunidade de remover campos que não estão mais em uso. O Hibernate não faz isso.

E acho que comparar o esquema de produção com o novo esquema oferece uma percepção ainda melhor do que você alterou no modelo de dados. Você sabe, é claro, porque fez isso, mas agora vê todas as mudanças de uma só vez. Mesmo aqueles que fazem você ir como "O que diabos ?!".

Existem ferramentas que podem criar um delta de esquema para você, portanto, nem é um trabalho árduo. E então você sabe exatamente o que vai acontecer.

extraneon
fonte
"Existem ferramentas que podem criar um delta de esquema para você": você poderia apontar para algumas dessas ferramentas?
Daniel Cassidy
Acho que apexsql.com/sql_tools_diff.asp faz isso e, possivelmente, mais aplicativos. Eu costumo fazer isso manualmente despejando o esquema e diffing (usando o diff).
usar o seguinte
2

O esquema dos aplicativos pode evoluir com o tempo; se você possui várias instalações, que podem estar em versões diferentes, você deve ter alguma maneira de garantir que seu aplicativo, algum tipo de ferramenta ou script seja capaz de migrar o esquema e os dados de uma versão passo a passo para outra.

Ter toda a sua persistência nos mapeamentos do Hibernate (ou anotações) é uma maneira muito boa de manter a evolução do esquema sob controle.

Você deve considerar que a evolução do esquema tem vários aspectos a serem considerados:

  1. evolução do esquema do banco de dados na adição de mais colunas e tabelas

  2. descarte de colunas, tabelas e relações antigas

  3. preenchendo novas colunas com padrões

As ferramentas de hibernação são importantes, especialmente no caso (como na minha experiência), você tem versões diferentes do mesmo aplicativo em muitos tipos diferentes de bancos de dados.

O ponto 3 é muito sensível se você estiver usando o Hibernate, como se você introduzir uma nova propriedade com valor booleano ou uma propriedade numérica, se o Hibernate encontrar algum valor nulo nessas colunas, se houver uma exceção.

Então, o que eu faria é: realmente use a capacidade de atualização de esquema das ferramentas Hibernate, mas você deve adicionar juntamente com alguns dados e retorno de chamada de manutenção de esquema, como para preencher padrões, descartar colunas não mais usadas e similares. Dessa maneira, você obtém as vantagens (scripts de atualização de esquema independentes do banco de dados e evita a codificação duplicada das atualizações, em peristência e em scripts), mas também abrange todos os aspectos da operação.

Por exemplo, se uma atualização de versão consiste simplesmente em adicionar uma propriedade com valor varchar (por isso, coluna), que pode ser nula, com a atualização automática, você será feito. Onde mais complexidade é necessária, mais trabalho será necessário.

Isso pressupõe que o aplicativo, quando atualizado, é capaz de atualizar seu esquema (isso pode ser feito), o que também significa que ele deve ter os direitos de usuário para fazê-lo no esquema. Se a política do cliente impedir isso (provavelmente caso do Lizard Brain), você precisará fornecer os scripts específicos do banco de dados.

Pietro Polsinelli
fonte