Eu amo a tecnologia sem servidor. Eu brinco e faço vários aplicativos sem servidor diferentes para experimentar outras tecnologias legais. Dentro do enorme conjunto de tecnologias que uso/experimentei, PlanetScale foi o banco de dados que usei principalmente para meus projetos pessoais, pois não havia nenhuma outra opção "boa" que o Prisma ORM suportasse .
PlanetScale é uma plataforma sem servidor MySQL que simplesmente vende o Vitess, um sistema de cluster de banco de dados para o dimensionamento horizontal do MySQL. Eles não escreveram seu próprio banco de dados - possivelmente contribuíram para isso, mas não o escreveram. Da documentação do Vitess:
A Vitess foi criada em 2010 para resolver os desafios de escalabilidade do MySQL que a equipe do YouTube enfrentou.
Neste artigo, vamos entender a estrutura desses bancos de dados fragmentados herdados não-ACID, por que eles são incapazes de oferecer suporte a algo tão crucial quanto integridade referencial e por que devemos evitar usá-los em nossos aplicativos. Este artigo é mais sobre a tecnologia da Vitess, embora eu tenha incluído PlanetScale no título porque, como mencionei acima, está apenas vendendo Vitess (com algumas ferramentas) como um serviço e eles ganharam força nos meses seguintes como sendo um banco de dados sem servidor "confiável".
Histórico
Minha pergunta inicial era por que ele diz que é impossível dimensionar um banco de dados PlanetScale com integridade referencial, pois em sua documentação afirma que:
A maneira comoFOREIGN KEY
restrições são implementadas no MySQL (ou melhor, no mecanismo de armazenamento InnoDB) interfere nas operações de DDL Online. Saiba mais nesta postagem do blog da Vitess.
Limitado a um único escopo de servidor MySQL,FOREIGN KEY
restrições são impossíveis de manter quando seus dados crescem e são divididos em vários servidores de banco de dados. Isso normalmente acontece quando você introduz particionamento/fragmentação funcional e/ou fragmentação horizontal.
Isso me levou a pensar:faça
FOREIGN KEY
restrições afetam a escalabilidade em geral? e se sim, como? Eu acho que é importante perceber que as junções de tabelas SQL são bastante caras, mas que eu saiba, não foi muito afetada pela integridade referencial? Agora, se estamos fazendo algo como análise de dados, obviamente não precisamos de integridade referencial, pois queremos apenas despejar nossos dados em uma única tabela, mas PlanetScale e Vitess se orgulham de serem usados por grandes aplicativos da web como o YouTube.
Isso me deixou confuso sobre por que eles descartaram a
FOREIGN KEY
como bancos de dados como CockroachDB e Spanner ainda mantêm a integridade referencial além de serem escaláveis. O que é integridade referencial e por que é importante?
Vamos começar com o básico, caso você seja novo. Acho que a maioria das pessoas lendo este post tem uma boa ideia do que está falando, mas vou explicar como uma formalidade. Em palavras simples, uma
FOREIGN KEY
constraint é uma chave de banco de dados que podemos usar para criar relações entre duas tabelas diferentes referenciando uma coluna ou um conjunto de colunas. A integridade referencial simplesmente se refere ao estado do banco de dados no qual todos os valores de todas as chaves são válidos. Por que é importante?
Agora que temos uma ideia do que são, vamos pular para a segunda parte:por que são importantes?
A integridade referencial é importante, pois evita que você introduza novos erros em seu banco de dados. É um recurso frequentemente fornecido por bancos de dados relacionais que impedem que usuários ou aplicativos insiram dados inconsistentes no banco de dados. Isso leva a uma qualidade de dados aprimorada, desenvolvimento mais rápido, muito menos bugs e consistência em todo o seu aplicativo.
Por que Vitess não tem?
Então, para entender por que o Vitess é incapaz de oferecer suporte à integridade referencial, precisamos mergulhar na arquitetura do banco de dados. Vitess é um banco de dados SQL não ACID fragmentado, não um banco de dados SQL ACID distribuído verdadeiro.
Agora, você deve estar se perguntando quais são esses termos. Deixe-me dividi-los para você:ACID é um acrônimo de Atomicidade, Consistência, Isolamento e Durabilidade.
Aqui, atomicidade refere-se a uma ação completando ou falhando completamente - nenhuma conclusão parcial de uma transação. Consistência refere-se à transação deixando o banco de dados em um estado válido. Isolamento significa simplesmente que duas transações são executadas sem qualquer interferência entre si, e durabilidade significa que as alterações da transação são salvas.
Um shard é uma partição horizontal de dados em um banco de dados e cada shard é mantido em uma instância de servidor de banco de dados separada para distribuir a carga. Então, quando nos referimos a um banco de dados fragmentado, estamos falando de algo assim. Agora, como eu disse anteriormente, o Vitess é um banco de dados SQL não ACID fragmentado, o que basicamente significa que NÃO garante as propriedades ACID das transações.
Por que descartá-lo?
Bem, o problema começa quando você tem um banco de dados MySQL com um esquema bem definido, e seu serviço se torna popular com o problema de muitas leituras atingindo o banco de dados. O que a maioria das pessoas faz aqui é começar a armazenar em cache as consultas executadas com frequência, mas as leituras não são mais ACIDic.
Junto com muitas leituras, ter uma quantidade excessiva de gravações em seu banco de dados é um problema sério que muitos podem enfrentar. Digamos que estamos prontos para incendiar nossos bolsos - podemos escalar verticalmente, adicionando mais RAM, um processador de 16 núcleos e muitos drives de estado sólido realmente rápidos.
É claro que ainda temos o problema das junções de tabelas SQL aumentando em complexidade, então você começa a desnormalizar para evitar junções entre tabelas.
Dei uma palestra no Prisma Meetup há algum tempo, onde expliquei os fundamentos do design de um banco de dados relacional. Um tópico que abordei aqui foi a desnormalização, se você estiver interessado, não deixe de conferir isso.
Mas a desnormalização é basicamente o processo em que você adiciona dados redundantes a tabelas em seu banco de dados, o que melhora o desempenho no custo do espaço em disco, pois você não está mais usando a energia da CPU para junções. Embora a desnormalização melhore a velocidade das leituras, é importante perceber que ela torna as gravações mais lentas.
No entanto, apesar de tudo isso, nosso banco de dados ainda é lento, então movemos os cálculos do banco de dados para o cliente, por exemplo, gerando um UUID ou atribuindo uma data.
Mesmo depois de tudo isso, as consultas ainda serão lentas - por isso, mantemos o resultado dos dados mais consultados prontos em um processo conhecido como materialização do banco de dados. Agora as leituras podem ser mais rápidas, mas as gravações estão ficando mais lentas a cada dia. A única situação lógica agora é descartar índices secundários.
Então, neste ponto, nosso banco de dados tem
- Nenhuma propriedade ACID devido ao armazenamento em cache
- Sem esquema normalizado
- Nenhum acionador
- Nenhum cálculo de banco de dados
- Nenhum índice secundário
Isso abriu o caminho para os bancos de dados Vitess e NoSQL, pois as empresas estavam tendo problemas com o dimensionamento de seus bancos de dados. Da maneira como foi projetado, eles não conseguiram manter a consistência dos dados, uma propriedade ACID, quando as transações abrangeram vários fragmentos diferentes. A integridade referencial tem tudo a ver com consistência quando os dados se estendem por vários fragmentos, portanto, faz sentido que eles não sejam capazes de oferecer suporte adequado.
Podemos ir fundo na estrutura dos bancos de dados NoSQL sem
FOREIGN KEY
restrição e problemas que enfrentaremos adotando esse modelo, mas isso é assunto para outro post. Não é apenas o Vitess, tem sido uma prática padrão para bancos de dados fragmentados evitar a integridade referencial, pois simplesmente não há outra opção. Em termos do modelo ACID, sua documentação afirma que eles garantem atomicidade, mas não isolamento, e chegam a dizer:
Garantir o Isolamento de ÁCIDO é muito controverso e tem custos elevados. Fornecê-lo por padrão tornaria o Vitess impraticável para os casos de uso mais comuns.
Vamos falar brevemente sobre o que é o ACID Isolation. Existem quatro níveis para ele (de acordo com os padrões SQL-92), incluindo serialização, leitura confirmada, leitura não confirmada e leituras repetíveis. Com isso dito, existem mais níveis de isolamento, como o isolamento Snapshot, que não é um padrão SQL, embora seja usado por vários bancos de dados, como Firebase ou MongoDB. Se você se interessou ainda mais por isso, recomendo a leitura deste post. Para ser breve, não vou falar sobre o que cada nível de isolamento faz/significa, mas se você quiser ler mais sobre isso, confira esta página da Documentação do MySQL.
O isolamento ACID refere-se às transações do banco de dados sendo ACIDic, o que é importante, pois garante que as operações se comportem da maneira que os desenvolvedores esperam. Não tenho certeza do que eles querem dizer quando dizem "Garantir o isolamento de ACID é muito controverso e tem custos altos", mas se eles querem dizer que garantir o isolamento de ACID tem altos custos para qualquer produto , eles estão errados. Vários bancos de dados distribuídos compatíveis com ACID têm o mais alto nível de isolamento (transações serializáveis), enquanto ainda apresentam desempenho com velocidades rápidas de leitura/gravação. No entanto, no contexto do Vitess, eles não estão errados, pois as transações de vários fragmentos não podem atender a nenhum nível de isolamento.
Conclusão
Com tudo isso, você deve estar se perguntando:por que alguém iria querer usar PlanetScale ou Vitess? Bem, eu me pergunto o mesmo. Com muitas empresas e sites, o motivo foi que eles escolheram a Vitess de volta quando não havia opções melhores. Se você for ao início do artigo, observe como ele foi criado em 2010. Agora que podemos desfrutar de um banco de dados escalável compatível com ACID com integridade referencial, seria de nosso interesse mudar para esses novos bancos de dados, e eu já comecei a fazer isso! A tecnologia muda rapidamente e manter seu banco de dados atualizado é um componente crucial de qualquer aplicativo.