Como resolver problemas de migrações

Você está desenvolvendo uma aplicação na sua estação. Cria, modifica, remove tabelas, chaves (constraints) e colunas, gera um monte de migrações (migrations) com o seu ORM favorito para manipular uma base de dados relacional e na hora do deploy o sistema quebra porque as migrações estão uma bagunça querendo remover coisas que não existem mais ou criar cosias que já existem.

Isso acontece e eu vou te mostrar aqui algumas formas de resolver.

O problema…

Na hora do desenvolvimento é normal que a gente faça muita alteração, afinal de contas, é nessa hora que podemos testar hipóteses e errar bastante, mas isso gera um certo “lixo” nas migrações que podem e vão nos dar trabalho futuramente.

Esse tipo de problema acontece normalmente com quem usa geradores de migração ou com desenvolvedores que as escrevem de forma muito simplista, assim como os geradores fazem.

Vejamos um exemplo gerado pelo gerador de migrações do Typeorm.

import {MigrationInterface, QueryRunner} from "typeorm";

export class ModifySomething implements MigrationInterface {
    name = 'ModifySomething987982495702935873450987'

    public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query("ALTER TABLE `syndicate` ADD CONSTRAINT `FK_sd9f8g7s8df6g89f6s87dfg` FOREIGN KEY (`addressId`) REFERENCES `address`(`id`) ON DELETE CASCADE ON UPDATE CASCADE");
        await queryRunner.query("ALTER TABLE `address` ADD CONSTRAINT `FK_c76sdf8g6sdf87g6s9g67` FOREIGN KEY (`companyId`) REFERENCES `company`(`id`) ON DELETE CASCADE ON UPDATE CASCADE");
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.query("ALTER TABLE `address` DROP FOREIGN KEY `FK_c76sdf8g6sdf87g6s9g67`");
        await queryRunner.query("ALTER TABLE `syndicate` DROP FOREIGN KEY `FK_sd9f8g7s8df6g89f6s87dfg`");
    }

}

Notem que ele não faz nenhuma verificação se as chaves existem ou não e em caso de uma coluna, se tem algum dado lá dentro.

Ele simplesmente sai fazendo loucamente e é isso que normalmente geram erros ao rodar as migrações. Porque o sistema tenta adicionar algo que já existe ou remover algo que não existe mais.

Erro de migração
A imagem mostra a tela do editor de códigos com um erro de migração

Forma fácil, mas…

A forma mais fácil de resolver esse tipo de problema depois que ele já aconteceu é encontrar a última migração que foi executada com sucesso, remover todas as seguintes e depois gerar uma nova migração com todas as modificações compiladas nela mesma, mas… (sempre tem um mas) se você trabalha com mais desenvolvedores, pode ser que você complique as coisas já que no commit anterior haviam as migrations com problemas e o novo tem a solução… não necessariamente vai dar problema, mas pode dar!

Faça isso por sua conta e risco, combine com o seu time e antes disso, faça backups e etc. Lembre-se que migrations servem para versionar o banco de dados e é importante manter o histórico. Depois que tudo der certo, se livre dessas tranqueiras.

Forma mais trabalhosa, mas…

A forma mais “trabalhosa” é você criar as migrações você mesmo, ou usar o código gerado pelo ORM (Typeorm nesse caso) e refatorá-lo fazendo as verificações necessárias.

Normalmente, os ORM’s oferecem funções que ajudam nesse sentido, como no caso do Typeorm que tem uma API específica para isso.

Basta você utilizar QueryRunner como injeção de dependência no seus métodos up() e down() e chamar os métodos que quiser, tais como: createTable(), createIndex(), addColumn(), createForeignKey(), getTable(), etc.

Nesse caso, o método getTable() é um método muito importante, já que ele trás as informações da tabela e com ele saberemos se a coluna a ser criada existe, se a chave estrangeira já foi criada, etc.

Então, essa é a forma mais “trabalhosa”, mas (sempre tem um mas…) a mais elegante também (você achou que vinha alguma coisa ruim aqui, certo? heheh)

Previna-se

Lembre-se que você provavelmente só está nessa situação porque não fez um bom planejamento da funcionalidade ou porque você “comitou” o código sem revisar antes e levou um monte de bugs para o seu repositório remoto.

Para prevenir isso é fácil, é só fazer as revisões, usar testes e nunca “comitar” direto na sua branch master. Caso você trabalhe sozinho (como uma “euquipe”) redobre os cuidados, pois resolver problemas de desenvolvimento é custo e você precisa de lucro, estou certo? Caso você tenha uma equipe com mais desenvolvedores, crie uma pull request e solicite as revisões de código, aos seus colegas, discuta as melhores formas de resolver o problema antes de fazer o merge para a master e evite problemas.

Não deixe seu sistema quebrar…

Quando uma migração não acontece, o seu sistema quebra e isso é ruim, certo?

Imagine você que seu sistema está funcionando “bonitamente” e na sexta-feira você tem a brilhante ideia de fazer o deploy de uma release super massinha. Está tudo indo bem, mas no último segundo para o expediente acabar a sua migração quebra e a API do seu sistema vai pro saco…

Isso aconteceu comigo e eu não quero que aconteça com você 🙂

Docker Swarm Vs. Kubernates
Mostra os logos de Docker Swarm versus Kubernates

A melhor ideia para resolver esse problema é utilizar orquestradores de containers, como o Kubernates ou Docker Swarm por exemplo.

Eles fazem um monte de coisas e uma delas é manter a API em pé e só subir a nova realease quando tudo estiver certinho.

Isso pode salvar seu final de semana e evitar muitos cabelos brancos.

Por hoje é isso aí!

Esperto muito ter ajudado.

Não esqueça de deixar um comentário bem bacana contando suas experiências e como eu posso ajudar 🙂

Grande abraço!

Licenciamento de Oracle Database: Virtualizar ou não?

Logotipo Oracle

Introdução

Estou liderando um projeto relativamente de grande porte na empresa em que trabalho. O desafio dessa vez é levar o ambiente para um datacenter aqui da cidade (Porto Alegre) ou melhorar as nossas dependências a fim de fornecer a segurança física necessária contra desastres, entretanto, havia a cerca de 3 anos outro projeto parado que o assunto era a criação de uma “nuvem privada”, somei os projetos e estou por aqui ficando quase de cabelo branco… (hehe).

No decorrer desse projeto, me deparei com a seguinte situação, virtualizar ou não virtualizar a minha instância de banco de dados?

No nosso caso utilizamos o Oracle como banco de dados principal na empresa. Nele temos nosso ERP, GED e CRM, além dele temos outros bancos de dados menores para outras tarefas, como intranet por exemplo, mas vamos nos ater ao Oracle.

Quando pensei em virtualizar, logo fui consultar o EULA da Oracle (como de praxe) para ver como ficariam as licenças para esse servidor. Entre diversos EULA’s, conversas com amigos, consultores, fornecedores e DBA’s, pude juntar as informações que forneço para vocês abaixo.

Importante: Não se baseie somente nessas informações, eu não trabalho para a Oracle, não sou certificado Oracle (ainda hehe) e essas informações servem somente como conhecimento e não como documento. Fiquem atentos as versões dos EULA’s fornecidos diretamente no site da fabricante do software. Não me responsabilizo por qualquer ação tomada com base nesse artigo.

Particionamento de servidor

A Oracle considera duas formas de “particionar” um servidor, são elas: soft partition e hard partition.

Abaixo algumas considerações sobre ambas.

Soft Partition

Soft partition é quando fazemos o particionamento em um hypervisor (VMWare, Citrix XenServer, Microsoft Hyper-V, etc). Quando configuramos a VM com um processador apenas.

Essa modalidade NÃO É ACEITA para o cálculo de número de processadores para aquisição de licenças Oracle.

Obs.: caso a virtualização seja feita sob o hypervisor da Oracle, o Oracle VM, existe outro documento permitindo contabilizar somente o processador da VM para licenciamento.

Hard Partition

Hard partition é quando conseguimos realmente especificar o hardware que será utilizado pelo sistema operacional. Essa modalidade sim é aceita pela Oracle como cálculo de numero de processadores para aquisição de licenças Oracle.

Entretanto, nas arquiteturas Intel x86 e x86_64 não são possíveis fazer hard partition, os SO’s não são preparados para isso, somente em arquiteturas RISC, como é o caso de Power (PPC) da IBM por exemplo.

Dessa forma é possível “informar” para o SO quanto de recurso físico ele vai utilizar, independentemente da máquina possuir no total dois processadores, por exemplo.

Licenças Oracle Database Standard Edition One e Oracle Database Standard Edition

A Oracle possui muitas outras licenças e formas de licenciamento, entretanto vou comentar apenas essas duas licenças de processador, as quais eu estudei para a implementação desse projeto.

Obs.: essas licenças podem ser pagas anualmente ou na forma perpétua.

Obs. 1: o valor do suporte anual é de 20% do valor das licenças, é preciso pagar para quantidade total de processadores que você tem e é muito importante que você tenha o suporte atualizado, caso contrário não terá direito de baixar pacotes de atualização do seu software e não terá suporte pela Oracle quando for necessário (geralmente quando chega a esse ponto é porque a coisa está muito, mas muito feia…). Outro motivo é que você paga retroativo, caso pule um ano, por exemplo (isso pode onerar o orçamento do seu departamento de TI e seu gestor certamente não vai gostar).

Considerações sobre Oracle Database Stanadard Edition One

Nessa edição, podemos licenciar equipamentos com até 2 processadores físicos. FIQUEM ATENTOS ENTRETANTO, que mesmo que a licença permita que sejam licenciados até dois processadores, não significa que uma máquina com dois processadores necessitará apenas de uma licença, pelo contrário, significa que caso tenha mais do que 2 processadores, deverá ser usada outro tipo de licença, falaremos disso mais adiante.

Além disso, esse licenciamento custa o equivalente a metade do valor da versão Standard (em 2013) e não possui direitos de uso de Oracle RAC (Real Application Cluster – Consiste basicamente em um conjunto de serviços de alta disponibilidade).

Exemplificando:

Exemplo 1: Um servidor com dois processadores físicos deverá utilizar duas licenças Oracle Database Standard Edition One.

Exemplo 2: Um servidor com quatro processadores físicos deverá utilizar outro tipo de licenciamento.

Exemplo 3: Um servidor com mais de quatro processarores físicos deverá utilizar um tipo de licenciamento diferente do comentado no Exemplo 2 (esse não será comentado nesse artigo).

Considerações sobre Oracle Database Stanadard Edition

Nessa versão, podemos utilizar em equipamentos com até 4 processadores físicos e o mesmo comentado na versão anterior vale para cá.

Essa versão é bem cara e contempla a utilização do Oracle RAC.

Obs.: Ainda existe a versão Enterprise para equipamentos com mais de 4 processadores, que possui um algoritmo de cálculo baseado no total dos cores dos processadores físicos multiplicado por 0,5, mas não vou comentar nada além disso nesse artigo, pois não estudei muito a fundo… além disso, dependendo do tamanho da empresa (quantidade de usuários, se está virtualizado ou não, falaremos mais adiante).

 

Considerações sobre utilização de virtualização

 

As formas de licenciamento supracitadas servem tanto para ambientes virtuais como físicos, entretanto devemos observar alguns pontos além dos já citados em ambientes virtuais. São eles:

Suporte

No projeto inicial iríamos virtualizar a instância de banco de dados sob o Microsoft Windows Server 2012 Hyper-V, entretanto um ponto levantado foi fortemente considerado. A Oracle “não presta suporte” á ambientes que não estão virtualizados com Oracle VM (até então). Na verdade, eles não vão deixar de te atender, mas vão te mandar simular o erro que está ocorrendo em uma máquina física (caso o erro ainda não esteja relatado), aí já viu que a dor de cabeça vira enxaqueca rapidinho…

Utilização de V-motion

Todos os hypervisors tem a possibilidade de v-motion (mover máquinas virtuais dentro de um grupo [pool] de servidores) que é uma ferramenta de excelente aplicabilidade em qualquer ambiente, principalmente quando utilizado com HA (High Available, alta disponibilidade).

Com a utilização desse serviço, a sua VM com a instância Oracle passará por diversos equipamentos e a política da Oracle é clara quanto à isso: toda a máquina que rodar o produto deverá ser licenciada. Portanto, se você tem um pool com 4 máquinas físicas por onde essa VM poderá passar por V-motion, você terá que licenciar todas as máquinas do pool.

Oracle VM

Conforme já citado, a Oracle tem um documento específico para o licenciamento sob Oracle VM, nesse caso é contato apenas o processador da máquina virtual em que está instalado o banco de dados.

Obs.: até então o Oracle VM não faz motion de storage, entretanto, isso não é um impecílio, o próprio storage tem tecnologia suficiente para suprir essa necessidade.

Conclusão

Conforme o estudo realizado sob as licenças Oracle, tive que alterar parte considerável do escopo do projeto inicial, inclusive os custos do projeto.

No meu caso, optei por não virtualizar, apenas utilizar uma máquina (host) específica para esse serviço, mas cada ambiente é um organismo e precisa ser avaliado de perto.

Essas são algumas considerações que eu tive para o meu projeto, mas não tome como documento, pergunte e informe-se em fontes garantidas, como o site da fabricante.

Você também pode contribuir para a comunidade. Tem alguma sugestão ou correção? Descreva nos comentários.

 

E você o que usou ou usaria em seu ambiente?

GRRF: Erro com banco de dados

Recentemente, tivemos problemas em instalar o GRRF em uma máquina no ambiente da Empresa.

Atualmente, trabalhamos com Domínios e usuários com direitos limitados e por esse fato, muitas aplicações dão um trabalho danado na hora de serem executadas. Não diferente, as aplicações do nosso Governo (geralmente dão mais trabalho), o aplicativo GRRF deu muita dor de cabeça por aqui.

Como encontramos a solução, vou disponibiliza-la para que a dor de cabeça de vocês seja menor que a minha…

ATENÇÃO

Se você não trabalha com infraestrutura de TI ou não é familiarizado com isso, apenas execute o programa como administrador. Tem um comentário do Felipe Fonseca aqui em baixo que explica como fazer isso e essa dica foi dada pela Myller Meirelles também nos comentários.
Caso contrário, segue o baile… valeu!

  1.  Primeiramente, é necessário setar permissão para o grupo de usuários em questão nos arquivos Hl_med32.dllHl_pub32.dllHlsoft32.dll localizados no diretório C:\WINDOWS\SYSTEM32.
  2. Depois, dê também permissão no diretório C:\WINDOWS\PREFETCH
  3. Também em C:\Arquivos de programas\Caixa e em HKLM\SOFTWARES\Caixa
  4. Vá no Painel de Controle > Ferramentas Administrativas > Diretivas de Segurança Local > Configurações de Segurança > Diretivas Locais > Atribuição de Direitos de Usuário > ‘Criar Objetos Globais’ > Adicionar o usuário ou adicione à uma GPO.
Mais auxílio para esse problema, pode ser encontrado nesse link (que foi de onde tirei tudo isso hehe) http://social.technet.microsoft.com/Forums/pt-BR/winvistapt/thread/905b1d18-90a3-4e50-80fe-028035209677
Abraço!