Databases Migrations

Databases Migrations

Introdução

Esse trimestre estou estudando a disciplina de DBRE(Database Reliability Engineer) no curso de Pós Graduação DevOps and Cloud Solutions do Mackenzie que está sendo ministrada pelo professor Walter o qual solicitou um trabalho acadêmico sobre migrations. Então porque não escrever um pequeno artigo sobre esse assunto, let's go! ✍🏼

Afinal que são databases Migrations?

Sendo bem direto ao ponto, migrations trata-se do gerenciamento de mudanças incrementais e reversíveis no seu schema(estrutura) de banco de dados, ou seja, um controle de versionamento do seu banco de dados em repositório de código como o github por exemplo.

O que é um seeder?

Seeders são semeadores, são utilizados para popular a base de dados. Normalmente é muito utilizado para inserir dados padrões no banco de dados para o funcionamento correto da aplicação ou para inserção de dados fake em um ambiente de dev para execução de testes.

Método Up()

O método up é utilizado para executar uma migration que foi criada e alterar propriamente dito o schema do seu banco de dados. Criar uma nova coluna, criar uma nova tabela por exemplo.

Médoto Down()

O método down é utilizado para reverter uma migration para a posição anterior, como se fosse um rollback na estrutura do seu banco de dados. Remover uma coluna que foi criada, remover uma nova tabela que foi criada por exemplo.

Mão na massa! 💻

Para exemplificar tudo que foi dito até agora, vamos executar um projeto bem simples. Trata-se de uma aplicação de catálogo de livros, que foi escrita em Node utilizando como migrations a biblioteca mysql-migration todos os detalhes estão no repositório nogithub.com/santospedroh/dbre-migration.

Executando a migration inicial

Faça o clone do projeto executando o comando: git clone https://github.com/santospedroh/dbre-migration.git observe que existe um diretório chamado src/migrations e dentro dele temos dois arquivos: 1655316346150_create_table_books.js e o 1655323973586_create_books.js. Esse hash numérico que vemos no início do nome do arquivo é um timestamp o qual a migrations utiliza para fazer o controle de versionamento.

➜  migrations git:(main) ls -ltr
total 16
-rw-r--r--  1 santospedroh  staff  199 15 Jun 19:52 1655316346150_create_table_books.js
-rw-r--r--  1 santospedroh  staff  377 15 Jun 19:52 1655323973586_create_books.js

O arquivo _create_table_books.js trata-se da migration inicial com a criação da tabela de livros.

module.exports = {
    "up": "CREATE TABLE books (id INT NOT NULL AUTO_INCREMENT, UNIQUE KEY id (id), capa TEXT, nome varchar(255), editora varchar(255), link TEXT)",
    "down": "DROP TABLE books"
}

O arquivo _create_books.js trata-se do seeder com a inserção de um registro de livro para a base não iniciar vazia.

module.exports = {
    "up": "INSERT INTO books (capa, nome, editora, link) VALUES ('https://lh3.googleusercontent.com/JvM0JKKuZNJMWAC5iZPm4j-mdS9ORpZbpEWzg0zmJ0i2_xgIcju0OLXJ-zmnvz_GtFFGHe9qZ9Dz-6W0u5fRLFQaRlOI_hGzbetw','Site Reliability Engineering','O Reilly Media','https://sre.google/books/');",
    "down": "DELETE FROM books WHERE nome='Site Reliability Engineering';"
}

Vou considerar que você já tem o Docker instalado em seu computador, caso você não tenha o docker instalado siga o passo a passo descrito no README.md do projeto.

Execute o seguinte comando docker: docker run --rm -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=rootpass -e MYSQL_USER=db_user -e MYSQL_PASSWORD=db_pass -e MYSQL_DATABASE=library -d mysql:5.6.51

Este comando irá criar um container docker com banco de dados MySQL 5.6 onde executaremos as migrations e a aplicação irá utilizar.

➜  ~ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED       STATUS       PORTS                    NAMES
0a806d5d41a8   mysql:5.6.51   "docker-entrypoint.s…"   2 hours ago   Up 2 hours   0.0.0.0:3306->3306/tcp   mysql

Agora para criar o schema basta executar o comando: ./src/migration.js up

migration-up-step-1

Para executar a aplicação e verificar se deu tudo certo execute o comando: node ./src/app_books.js

app-step-1

Alterando a aplicação, adicionando colunas na tabela

Agora vamos acessar a branch release-1.0 do projeto o qual existe uma alteração que adiciona os novos campos autor e número de páginas para a entidade livros (tabela books).

Criando a nova migration e o novo seeder

Será necessário criar mais uma migration, para adicionar as colunas na tabela e mais um seeder, para atualizar o registro exemplo do livro.

Para criar a nova migration execute:

➜  migrations git:(main) node .src/migration.js add migration add_columns_books

Para criar o novo seeder execute:

➜  migrations git:(main) node .src/migration.js add seed add_autor_pags

Mais dois arquivos serão criados dentro do diretório src/migrations com os métodos up e down.

migration-step-2

Precisamos inserir as instruções SQL nestes arquivos conforme abaixo:

O arquivo _add_columns_books.js trata-se da migration para adicionar as novas colunas.

module.exports = {
    "up": "ALTER TABLE books ADD COLUMN autor varchar(255), ADD COLUMN num_pags INT",
    "down": "ALTER TABLE books DROP COLUMN autor, DROP COLUMN num_pags"
}

O arquivo _add_autor_pags.js trata-se do seeder com a inserção do autor e número de páginas para registro do livro.

module.exports = {
    "up": "UPDATE books SET autor='Betsy Beyer, Chris Jones, Jennifer Petoff, Niall Richard Murphy', num_pags=524 WHERE nome='Site Reliability Engineering';",
    "down": "UPDATE books SET autor=NULL, num_pags=NULL WHERE nome='Site Reliability Engineering';"
}

migration-step-3

Executando a nova migration

Agora para alterar o schema basta executar novamente o comando: node ./src/migration.js up

migration-step-4

Para executar a aplicação e verificar se deu tudo certo execute o comando: node ./src/app_books.js

app-step-2

Voltar versão anterior do schema

Para voltar para o estado anterior do schema do banco de dados basta executar o comando: node ./src/migration.js down 2 vezes, a primeira irá reverter o seeder com os dados dos campos autor e número de páginas e a segunda irá reverter a migration removendo as colunas autor e num_pags da tabela books.

➜  dbre-migration git:(release-1.0) ✗ node ./src/migration.js down
Run: true Type: DOWN: UPDATE books SET autor=NULL, num_pags=NULL WHERE nome='Site Reliability Engineering';
No more DOWN migrations to run
finished running migrations
➜  dbre-migration git:(release-1.0) ✗ node ./src/migration.js down
Run: true Type: DOWN: ALTER TABLE books DROP COLUMN autor, DROP COLUMN num_pags
No more DOWN migrations to run
finished running migrations

migration-step-5

Conclusão

Migrations é uma ótima maneira de versionar o schema da sua base de dados junto com o código fonte da sua aplicação no repositório git. Para este hands-on eu utilizei a biblioteca do npm mysql-migration que é bem simples porém vários frameworks em várias linguagens já tem suporte nativo a migrations.