MariaDB
 sql >> Base de Dados >  >> RDS >> MariaDB

Dicas de gerenciamento de esquema para MySQL e MariaDB


O esquema de banco de dados não é algo que está escrito em pedra. Ele é projetado para um determinado aplicativo, mas os requisitos podem e geralmente mudam. Novos módulos e funcionalidades são adicionados ao aplicativo, mais dados são coletados, código e refatoração do modelo de dados é realizada. Daí a necessidade de modificar o esquema do banco de dados para se adaptar a essas mudanças; adicionar ou modificar colunas, criar novas tabelas ou particionar as grandes. As consultas também mudam à medida que os desenvolvedores adicionam novas maneiras de os usuários interagirem com os dados - novas consultas podem usar índices novos e mais eficientes, então corremos para criá-los para fornecer ao aplicativo o melhor desempenho de banco de dados.

Então, como abordamos melhor uma mudança de esquema? Quais ferramentas são úteis? Como minimizar o impacto em um banco de dados de produção? Quais são os problemas mais comuns com o design do esquema? Quais ferramentas podem ajudá-lo a ficar no topo do seu esquema? Nesta postagem do blog, forneceremos uma breve visão geral de como fazer alterações de esquema no MySQL e no MariaDB. Observe que não discutiremos alterações de esquema no contexto do Galera Cluster. Já discutimos o isolamento total de pedidos, atualizações de esquemas contínuos e dicas para minimizar o impacto do RSU em postagens anteriores do blog. Também discutiremos dicas e truques relacionados ao design de esquema e como o ClusterControl pode ajudá-lo a ficar por dentro de todas as alterações de esquema.

Tipos de alterações de esquema


Primeiras coisas primeiro. Antes de nos aprofundarmos no tópico, precisamos entender como o MySQL e o MariaDB realizam alterações de esquema. Veja, uma mudança de esquema não é igual a outra mudança de esquema.

Você já deve ter ouvido falar sobre alters online, alters instantâneos ou alters in-place. Tudo isso é resultado de um trabalho contínuo para minimizar o impacto das alterações de esquema no banco de dados de produção. Historicamente, quase todas as alterações de esquema estavam bloqueando. Se você executou uma alteração de esquema, todas as consultas começarão a se acumular, aguardando a conclusão de ALTER. Obviamente, isso representava sérios problemas para implantações de produção. Claro, as pessoas imediatamente começam a procurar soluções alternativas, e as discutiremos mais tarde neste blog, pois ainda hoje elas ainda são relevantes. Mas também começou o trabalho para melhorar a capacidade do MySQL de executar DDLs (Data Definition Language) sem muito impacto em outras consultas.

Mudanças instantâneas


Às vezes, não é necessário tocar em nenhum dado no tablespace, porque tudo o que precisa ser alterado são os metadados. Um exemplo aqui será descartar um índice ou renomear uma coluna. Tais operações são rápidas e eficientes. Normalmente, seu impacto é limitado. Não é sem qualquer impacto, no entanto. Às vezes, leva alguns segundos para realizar a alteração nos metadados e essa alteração requer que um bloqueio de metadados seja adquirido. Este bloqueio é por tabela e pode bloquear outras operações que devem ser executadas nesta tabela. Você verá isso como entradas "Aguardando bloqueio de metadados de tabela" na lista de processos.

Um exemplo de tal mudança pode ser o ADD COLUMN instantâneo, introduzido no MariaDB 10.3 e MySQL 8.0. Dá a possibilidade de executar esta mudança de esquema bastante popular sem qualquer atraso. Tanto o MariaDB quanto o Oracle decidiram incluir o código do Tencent Game que permite adicionar instantaneamente uma nova coluna à tabela. Isso ocorre sob algumas condições específicas; A coluna deve ser adicionada como a última, os índices de texto completo não podem existir na tabela, o formato da linha não pode ser compactado - você pode encontrar mais informações sobre como a adição instantânea de colunas funciona na documentação do MariaDB. Para MySQL, a única referência oficial pode ser encontrada no blog mysqlserverteam.com, embora exista um bug para atualizar a documentação oficial.

Mudanças no local


Algumas das mudanças requerem modificação dos dados no tablespace. Tais modificações podem ser realizadas nos próprios dados, não sendo necessário criar uma tabela temporária com uma nova estrutura de dados. Essas alterações normalmente (embora nem sempre) permitem que outras consultas que tocam na tabela sejam executadas enquanto a alteração do esquema está em execução. Um exemplo dessa operação é adicionar um novo índice secundário à tabela. Esta operação levará algum tempo para ser executada, mas permitirá que DMLs sejam executados.

Reconstrução de tabela


Se não for possível fazer uma alteração no local, o InnoDB criará uma tabela temporária com a nova estrutura desejada. Em seguida, ele copiará os dados existentes para a nova tabela. Esta operação é a mais cara e é provável (embora nem sempre aconteça) o bloqueio das DML's. Como resultado, essa alteração de esquema é muito difícil de executar em uma tabela grande em um servidor autônomo, sem a ajuda de ferramentas externas - normalmente você não pode ter seu banco de dados bloqueado por longos minutos ou mesmo horas. Um exemplo dessa operação seria alterar o tipo de dados da coluna, por exemplo, de INT para VARCHAR.

Mudanças de esquema e replicação


Ok, então sabemos que o InnoDB permite alterações de esquema online e se consultarmos a documentação do MySQL, veremos que a maioria das alterações de esquema (pelo menos entre as mais comuns) podem ser realizadas online. Qual é a razão por trás de dedicar horas de desenvolvimento para criar ferramentas de mudança de esquema online como gh-ost? Podemos aceitar que pt-online-schema-change é um resquício dos velhos tempos ruins, mas gh-ost é um novo software.

A resposta é complexa. Existem duas questões principais.

Para começar, uma vez que você inicia uma mudança de esquema, você não tem controle sobre ela. Você pode abortá-lo, mas não pode pausá-lo. Você não pode estrangulá-lo. Como você pode imaginar, reconstruir a tabela é uma operação cara e mesmo que o InnoDB permita que DMLs sejam executados, a carga de trabalho de E/S adicional do DDL afeta todas as outras consultas e não há como limitar esse impacto a um nível aceitável para o inscrição.

Em segundo lugar, questão ainda mais séria, é a replicação. Se você executar uma operação sem bloqueio, que requer uma reconstrução de tabela, ela de fato não bloqueará DMLs, mas isso é verdade apenas no mestre. Vamos supor que esse DDL levou 30 minutos para ser concluído - a velocidade de ALTER depende do hardware, mas é bastante comum ver esses tempos de execução em tabelas de intervalo de tamanho de 20 GB. Em seguida, ele é replicado para todos os escravos e, a partir do momento em que o DDL inicia nesses escravos, a replicação aguardará sua conclusão. Não importa se você usa MySQL ou MariaDB, ou se tem replicação multi-thread. Os escravos ficarão atrasados ​​- eles aguardarão esses 30 minutos para que o DDL seja concluído antes de começar a aplicar os eventos de log binário restantes. Como você pode imaginar, 30 minutos de atraso (às vezes até 30 segundos não serão aceitáveis ​​- tudo depende do aplicativo) é algo que impossibilita o uso desses escravos para dimensionamento. Claro, existem soluções alternativas - você pode realizar alterações de esquema de baixo para cima da cadeia de replicação, mas isso limita seriamente suas opções. Especialmente se você usar a replicação baseada em linha, só poderá executar alterações de esquema compatíveis dessa maneira. Alguns exemplos de limitações de replicação baseada em linha; você não pode descartar nenhuma coluna que não seja a última, não pode adicionar uma coluna em uma posição diferente da última. Você também não pode alterar o tipo de coluna (por exemplo, INT -> VARCHAR).

Como você pode ver, a replicação adiciona complexidade à forma como você pode realizar alterações de esquema. As operações que não são bloqueantes no host autônomo tornam-se bloqueantes enquanto executadas nos escravos. Vamos dar uma olhada em alguns métodos que você pode usar para minimizar o impacto das alterações de esquema.

Ferramentas de alteração de esquema on-line


Como mencionamos anteriormente, existem ferramentas que se destinam a realizar alterações de esquema. Os mais populares são pt-online-schema-change criado por Percona e gh-ost, criado pelo GitHub. Em uma série de postagens no blog, nós os comparamos e discutimos como o gh-ost pode ser usado para realizar alterações de esquema e como você pode acelerar e reconfigurar uma migração em andamento. Aqui não entraremos em detalhes, mas ainda gostaríamos de mencionar alguns dos aspectos mais importantes do uso dessas ferramentas. Para começar, uma mudança de esquema executada por meio de pt-osc ou gh-ost acontecerá em todos os nós do banco de dados de uma só vez. Não há qualquer atraso em termos de quando a alteração será aplicada. Isso possibilita o uso dessas ferramentas mesmo para alterações de esquema incompatíveis com a replicação baseada em linha. Os mecanismos exatos sobre como essas ferramentas rastreiam as alterações na tabela são diferentes (triggers em pt-osc vs. binlog parsing em gh-ost), mas a ideia principal é a mesma - uma nova tabela é criada com o esquema desejado e os dados existentes são copiado da tabela antiga. Enquanto isso, os DMLs são rastreados (de uma forma ou de outra) e aplicados à nova tabela. Depois que todos os dados são migrados, as tabelas são renomeadas e a nova tabela substitui a antiga. Esta é uma operação atômica, portanto, não é visível para o aplicativo. Ambas as ferramentas têm a opção de estrangular a carga e pausar as operações. Gh-ost pode parar toda a atividade, pt-osc só pode parar o processo de cópia de dados entre a tabela antiga e a nova - os gatilhos permanecerão ativos e continuarão duplicando os dados, o que adiciona alguma sobrecarga. Devido à tabela de renomeação, ambas as ferramentas têm algumas limitações em relação a chaves estrangeiras - não suportadas por gh-ost, suportadas parcialmente por pt-osc seja por meio de ALTER regular, o que pode causar atraso de replicação (não viável se a tabela filho for grande) ou por descartar a tabela antiga antes de renomear a nova - é perigoso, pois não há como reverter se, por algum motivo, os dados não foram copiados para a nova tabela corretamente. Os gatilhos também são difíceis de suportar.

Eles não são suportados em gh-ost, pt-osc no MySQL 5.7 e mais recente tem suporte limitado para tabelas com triggers existentes. Outras limitações importantes para as ferramentas de alteração de esquema online é que a chave primária ou exclusiva deve existir na tabela. Ele é usado para identificar linhas a serem copiadas entre tabelas antigas e novas. Essas ferramentas também são muito mais lentas que o ALTER direto - uma alteração que leva horas durante a execução do ALTER pode levar dias quando realizada usando pt-osc ou gh-ost.

Por outro lado, como mencionamos, desde que os requisitos sejam atendidos e as limitações não entrem em jogo, você pode executar todas as alterações de esquema utilizando uma das ferramentas. Tudo acontecerá ao mesmo tempo em todos os hosts, portanto, você não precisa se preocupar com a compatibilidade. Você também tem algum nível de controle sobre como o processo é executado (menos em pt-osc, muito mais em gh-ost).

Você pode reduzir o impacto da mudança de esquema, você pode pausá-los e deixá-los rodar apenas sob supervisão, você pode testar a mudança antes de realizá-la. Você pode fazer com que eles rastreiem o atraso e a pausa da replicação caso um impacto seja detectado. Isso torna essas ferramentas uma ótima adição ao arsenal do DBA ao trabalhar com a replicação do MySQL.

Mudanças contínuas de esquema


Normalmente, um DBA usará uma das ferramentas de alteração de esquema online. Mas, como discutimos anteriormente, em algumas circunstâncias, eles não podem ser usados ​​e uma alteração direta é a única opção viável. Se estamos falando de MySQL autônomo, você não tem escolha - se a mudança não for bloqueante, isso é bom. Se não for, bem, não há nada que você possa fazer sobre isso. Mas então, muitas pessoas não executam o MySQL como instâncias únicas, certo? Que tal replicação? Como discutimos anteriormente, a alteração direta no mestre não é viável - na maioria dos casos, causará atraso no escravo e isso pode não ser aceitável. O que pode ser feito, porém, é executar a mudança de forma contínua. Você pode começar com slaves e, uma vez que a mudança seja aplicada em todos eles, promova um dos slaves como um novo master, rebaixe o antigo master para slave e execute a alteração nele. Claro, a mudança tem que ser compatível, mas, para falar a verdade, os casos mais comuns em que você não pode usar mudanças de esquema online é por falta de chave primária ou exclusiva. Para todos os outros casos, existe algum tipo de solução alternativa, especialmente em pt-online-schema-change, pois o gh-ost tem limitações mais difíceis. É uma solução alternativa que você chamaria de “tão tão” ou “longe do ideal”, mas fará o trabalho se você não tiver outra opção para escolher. O que também é importante, a maioria das limitações pode ser evitada se você monitorar seu esquema e detectar os problemas antes que a tabela cresça. Mesmo que alguém crie uma tabela sem uma chave primária, não é um problema executar uma alteração direta que leva meio segundo ou menos, pois a tabela está quase vazia.

Se crescer, isso se tornará um problema sério, mas cabe ao DBA detectar esse tipo de problema antes que eles realmente comecem a criar problemas. Abordaremos algumas dicas e truques sobre como garantir que você detecte esses problemas a tempo. Também compartilharemos dicas genéricas sobre como projetar seus esquemas.

Dicas e truques

Design de esquema


Como mostramos neste post, as ferramentas de alteração de esquema online são muito importantes ao trabalhar com uma configuração de replicação, portanto, é muito importante garantir que seu esquema seja projetado de forma que não limite suas opções para realizar alterações de esquema. Existem três aspectos importantes. Primeiro, a chave primária ou exclusiva deve existir - você precisa garantir que não haja tabelas sem uma chave primária em seu banco de dados. Você deve monitorar isso regularmente, caso contrário, pode se tornar um problema sério no futuro. Em segundo lugar, você deve considerar seriamente se usar chaves estrangeiras é uma boa ideia. Claro, eles têm seus usos, mas também adicionam sobrecarga ao seu banco de dados e podem tornar problemático o uso de ferramentas de alteração de esquema online. As relações podem ser impostas pelo aplicativo. Mesmo que isso signifique mais trabalho, ainda pode ser uma ideia melhor do que começar a usar chaves estrangeiras e ficar severamente limitado a quais tipos de alterações de esquema podem ser executadas. Terceiro, gatilhos. Mesma história das chaves estrangeiras. Eles são um bom recurso para se ter, mas podem se tornar um fardo. Você precisa considerar seriamente se os ganhos de usá-los superam as limitações que eles representam.

Acompanhamento de alterações no esquema


O gerenciamento de alterações de esquema não se trata apenas de executar alterações de esquema. Você também precisa ficar por dentro da estrutura do esquema, especialmente se não for o único a fazer as alterações.

O ClusterControl fornece aos usuários ferramentas para rastrear alguns dos problemas de design de esquema mais comuns. Ele pode ajudá-lo a rastrear tabelas que não possuem chaves primárias:

Como discutimos anteriormente, capturar essas tabelas antecipadamente é muito importante, pois as chaves primárias precisam ser adicionadas usando alter direto.

O ClusterControl também pode ajudá-lo a rastrear índices duplicados. Normalmente, você não deseja ter vários índices redundantes. No exemplo acima, você pode ver que há um índice em (k, c) e também há um índice em (k). Qualquer consulta que pode usar o índice criado na coluna 'k' também pode usar um índice composto criado nas colunas (k, c). Há casos em que é benéfico manter índices redundantes, mas você deve abordá-lo caso a caso. A partir do MySQL 8.0, é possível testar rapidamente se um índice é realmente necessário ou não. Você pode tornar um índice redundante ‘invisível’ executando:
ALTER TABLE sbtest.sbtest1 ALTER INDEX k_1 INVISIBLE;

Isso fará com que o MySQL ignore esse índice e, por meio do monitoramento, você possa verificar se houve algum impacto negativo no desempenho do banco de dados. Se tudo funcionar conforme planejado por algum tempo (alguns dias ou até semanas), você pode planejar a remoção do índice redundante. Caso você detecte que algo não está certo, você sempre pode reativar esse índice executando:
ALTER TABLE sbtest.sbtest1 ALTER INDEX k_1 VISIBLE;

Essas operações são instantâneas e o índice está lá o tempo todo, e ainda é mantido - só que não será levado em consideração pelo otimizador. Graças a esta opção, remover índices no MySQL 8.0 será uma operação muito mais segura. Nas versões anteriores, adicionar novamente um índice removido incorretamente pode levar horas, se não dias, em tabelas grandes.

O ClusterControl também pode informá-lo sobre as tabelas MyISAM.

Embora o MyISAM ainda possa ter seus usos, você deve ter em mente que ele não é um mecanismo de armazenamento transacional. Como tal, ele pode facilmente introduzir inconsistência de dados entre nós em uma configuração de replicação.

Outro recurso muito útil do ClusterControl é um dos relatórios operacionais - um Relatório de Mudança de Esquema.

Em um mundo ideal, um DBA revisa, aprova e implementa todas as mudanças de esquema. Infelizmente, nem sempre é assim. Esse processo de revisão simplesmente não combina com o desenvolvimento ágil. Além disso, a proporção de desenvolvedor para DBA normalmente é bastante alta, o que também pode se tornar um problema, pois os DBAs lutam para não se tornar um gargalo. É por isso que não é incomum ver mudanças de esquema realizadas fora do conhecimento do DBA. No entanto, o DBA geralmente é o responsável pelo desempenho e estabilidade do banco de dados. Graças ao Relatório de Mudanças de Esquema, eles agora podem acompanhar as mudanças de esquema.

No início, alguma configuração é necessária. Em um arquivo de configuração para um determinado cluster (/etc/cmon.d/cmon_X.cnf), você deve definir em qual host o ClusterControl deve rastrear as alterações e quais esquemas devem ser verificados.
schema_change_detection_address=10.0.0.126
schema_change_detection_databases=sbtest

Feito isso, você pode agendar um relatório para ser executado regularmente. Um exemplo de saída pode ser como abaixo:

Como você pode ver, duas tabelas foram alteradas desde a execução anterior do relatório. Na primeira, um novo índice composto foi criado nas colunas (k, c). Na segunda tabela, uma coluna foi adicionada.

Na execução subsequente, obtivemos informações sobre a nova tabela, que foi criada sem nenhum índice ou chave primária. Usando esse tipo de informação, podemos agir facilmente quando necessário e resolver os problemas antes que eles realmente comecem a se tornar bloqueadores.