Lógica de negócios no banco de dados usando SchemaKeeper

O objetivo deste artigo é usar o exemplo de uma biblioteca guardião do esquema mostram ferramentas que podem simplificar significativamente o processo de desenvolvimento de bancos de dados em projetos PHP usando o SGBD PostgreSQL.

As informações deste artigo serão, em primeiro lugar, úteis para desenvolvedores que desejam aproveitar ao máximo os recursos do PostgreSQL, mas enfrentam problemas para manter a lógica de negócios colocada no banco de dados.

Este artigo não descreverá as vantagens ou desvantagens de armazenar lógica de negócios em um banco de dados. Supõe-se que a escolha já tenha sido feita pelo leitor.

Serão consideradas as seguintes questões:

  1. De que forma um dump da estrutura do banco de dados deve ser armazenado em um sistema de controle de versão (doravante denominado VCS)
  2. Como rastrear alterações na estrutura do banco de dados após salvar um dump
  3. Como transferir alterações na estrutura do banco de dados para outros ambientes sem conflitos e arquivos de migração gigantes
  4. Como organizar o processo de trabalho paralelo em um projeto por vários desenvolvedores
  5. Como implantar com segurança mais alterações na estrutura do banco de dados em um ambiente de produção

    SchemaKeeper projetado para trabalhar com procedimentos armazenados escritos na linguagem PL / pgSQL. Não foram realizados testes com outros idiomas, portanto o uso pode não ser tão eficaz ou não ser possível.

Como armazenar um dump da estrutura do banco de dados no VCS

Biblioteca guardião do esquema fornece uma função saveDump, que salva a estrutura de todos os objetos do banco de dados como arquivos de texto separados. A saída é um diretório contendo a estrutura do banco de dados, dividido em arquivos agrupados que podem ser facilmente adicionados ao VCS.

Vejamos como converter objetos de um banco de dados em arquivos usando vários exemplos:

Tipo de objeto
Condução
Nome
Caminho relativo para arquivo

mesa
público
contas
./public/tables/accounts.txt

Procedimento armazenado
público
autenticação (hash bigint)
./public/functions/auth(int8).sql

Introdução
reserva
Tarifas
./booking/views/tariffs.txt

O conteúdo dos arquivos é uma representação textual da estrutura de um objeto de banco de dados específico. Por exemplo, para procedimentos armazenados, o conteúdo do arquivo será a definição completa do procedimento armazenado, começando com o bloco CREATE OR REPLACE FUNCTION.

Como pode ser visto na tabela acima, o caminho para o arquivo armazena informações sobre o tipo, esquema e nome do objeto. Essa abordagem facilita a navegação pelo dump e pela revisão do código das alterações no banco de dados.

extensão .sql para arquivos com código-fonte de procedimento armazenado, foi selecionado para que o IDE forneça automaticamente ferramentas de interação com o banco de dados quando o arquivo for aberto.

Como rastrear alterações na estrutura do banco de dados após salvar um dump

Ao salvar um dump da estrutura atual do banco de dados no VCS, temos a oportunidade de verificar se foram feitas alterações na estrutura do banco de dados após a criação do dump. Na biblioteca guardião do esquema para detectar alterações na estrutura do banco de dados, uma função é fornecida verifyDump, que retorna informações sobre as diferenças sem efeitos colaterais.

Uma forma alternativa de verificar é chamar a função novamente saveDump, especificando o mesmo diretório e verifique se há alterações no VCS. Como todos os objetos do banco de dados são salvos em arquivos separados, o VCS mostrará apenas os objetos alterados.
A principal desvantagem deste método é a necessidade de sobrescrever os arquivos para ver as alterações.

Como transferir alterações na estrutura do banco de dados para outros ambientes sem conflitos e arquivos de migração gigantes

Graças à função deployDump O código-fonte dos procedimentos armazenados pode ser editado exatamente da mesma maneira que o código-fonte normal do aplicativo. Você pode adicionar/excluir novas linhas no código do procedimento armazenado e enviar imediatamente as alterações para o controle de versão ou criar/excluir procedimentos armazenados criando/excluindo os arquivos correspondentes no diretório de despejo.

Por exemplo, para criar um novo procedimento armazenado em um esquema public basta criar um novo arquivo com a extensão .sql no diretório public/functions, coloque nele o código-fonte do procedimento armazenado, incluindo o bloco CREATE OR REPLACE FUNCTION, então chame a função deployDump. Modificar e excluir um procedimento armazenado ocorre da mesma maneira. Assim, o código vai para o VCS e para o banco de dados ao mesmo tempo.

Se aparecer um erro no código-fonte de qualquer procedimento armazenado ou uma discrepância entre os nomes do arquivo e o procedimento armazenado, então deployDump falhará, exibindo texto de erro. A incompatibilidade de procedimentos armazenados entre o dump e o banco de dados atual é impossível ao usar deployDump.

Ao criar um novo procedimento armazenado, não há necessidade de inserir manualmente o nome de arquivo correto. Basta que o arquivo tenha a extensão .sql. Depois da ligação deployDump o texto do erro conterá o nome correto, que pode ser usado para renomear o arquivo.

deployDump permite alterar os parâmetros de uma função ou tipo de retorno sem ações adicionais, enquanto com a abordagem clássica você teria que
execute primeiro DROP FUNCTION, e só então CREATE OR REPLACE FUNCTION.

Infelizmente, existem algumas situações em que deployDump incapaz de aplicar alterações automaticamente. Por exemplo, se uma função de gatilho usada por pelo menos um gatilho for removida. Tais situações são resolvidas manualmente por meio de arquivos de migração.

Se você for responsável pela migração de alterações em procedimentos armazenados guardião do esquema, os arquivos de migração deverão ser usados ​​para transferir outras alterações na estrutura. Por exemplo, uma boa biblioteca para trabalhar com migrações é doutrina/migrações.

As migrações devem ser aplicadas antes do lançamento deployDump. Isso permite que você faça todas as alterações na estrutura e resolva situações problemáticas para que as alterações nos procedimentos armazenados sejam posteriormente transferidas sem problemas.

O trabalho com migrações será descrito com mais detalhes nas seções a seguir.

Como organizar o processo de trabalho paralelo em um projeto por vários desenvolvedores

É necessário criar um script para a inicialização completa do banco de dados, que será lançado pelo desenvolvedor em sua máquina de trabalho, adequando a estrutura do banco de dados local ao dump salvo no VCS. A maneira mais fácil é dividir a inicialização do banco de dados local em 3 etapas:

  1. Importe um arquivo com uma estrutura básica que será chamada, por exemplo. base.sql
  2. Aplicando Migrações
  3. Desafio deployDump

base.sql é o ponto de partida sobre o qual as migrações são aplicadas e executadas deployDumpIsto é, base.sql + миграции + deployDump = актуальная структура БД. Você pode criar esse arquivo usando o utilitário pg_dump. usado base.sql exclusivamente ao inicializar o banco de dados do zero.

Vamos chamar o script para inicialização completa do banco de dados refresh.sh. O fluxo de trabalho pode ser assim:

  1. O desenvolvedor lança em seu ambiente refresh.sh e obtém a estrutura atual do banco de dados
  2. O desenvolvedor começa a trabalhar na tarefa em questão, modificando o banco de dados local para atender às necessidades da nova funcionalidade (ALTER TABLE ... ADD COLUMN etc)
  3. Após concluir a tarefa, o desenvolvedor chama a função saveDumppara confirmar as alterações feitas no banco de dados no VCS
  4. Relançamento do desenvolvedor refresh.shem seguida verifyDumpque agora mostra uma lista de alterações a serem incluídas na migração
  5. O desenvolvedor transfere todas as alterações de estrutura para o arquivo de migração e executa novamente refresh.sh и verifyDumpe, se a migração for compilada corretamente, verifyDump não mostrará diferenças entre o banco de dados local e o dump salvo

O processo descrito acima é compatível com os princípios do gitflow. Cada ramificação no VCS conterá sua própria versão do dump e, ao mesclar as ramificações, os dumps serão mesclados. Na maioria dos casos, nenhuma ação adicional precisa ser tomada após uma mesclagem, mas se forem feitas alterações em ramificações diferentes, por exemplo, na mesma tabela, poderá surgir um conflito.

Consideremos uma situação de conflito usando um exemplo: existe uma filial desenvolver, do qual se ramificam dois ramos: feature1 и feature2, que não têm conflitos com desenvolver, mas têm conflitos entre si. A tarefa é fundir ambos os ramos em desenvolver. Para este caso, recomenda-se primeiro mesclar uma das ramificações em desenvolvere depois mesclar desenvolver para a ramificação restante, resolvendo conflitos na ramificação restante e, em seguida, mesclando a última ramificação em desenvolver. Durante a fase de resolução de conflitos, talvez seja necessário corrigir o arquivo de migração na última ramificação para que ele corresponda ao dump final, que inclui os resultados das mesclagens.

Como implantar com segurança mais alterações na estrutura do banco de dados em um ambiente de produção

Graças à presença de um dump da estrutura do banco de dados atual no VCS, é possível verificar o banco de dados de produção quanto à conformidade exata com a estrutura necessária. Isso garante que todas as alterações pretendidas pelos desenvolvedores foram transferidas com sucesso para a base de produção.

Como DDL no PostgreSQL é transacional, é recomendável seguir a seguinte ordem de implantação, para que, em caso de erro inesperado, você possa executar “sem dor” ROLLBACK:

  1. Iniciar transação
  2. Execute todas as migrações em uma transação
  3. Na mesma transação, execute deployDump
  4. Sem concluir a transação, execute verifyDump. Se não houver erros, execute COMMIT. Se houver erros, execute ROLLBACK

Essas etapas podem ser facilmente integradas às abordagens existentes para implantação de aplicativos, incluindo tempo de inatividade zero.

Conclusão

Graças aos métodos descritos acima, é possível extrair o máximo desempenho de projetos “PHP + PostgreSQL”, sacrificando relativamente pouca conveniência de desenvolvimento em comparação com a implementação de toda a lógica de negócios no código principal do aplicativo. Além disso, o processamento de dados em PL / pgSQL muitas vezes parece mais transparente e requer menos código do que a mesma funcionalidade escrita em PHP.

Fonte: habr.com

Adicionar um comentário