Esses bancos utilizam a linguagem SQL (Structured Query Language), que é uma linguagem declarativa (e não imperativa como C++) para manipulação dos dados em banco de dados relacionais (inserir, alterar e excluir dados). A linguagem foi criada em 1974 e teve sua padronização (SQL ANSI) em 1986, formalmente: SQL-86
Cada banco de dados relacional utiliza uma extensão dessa linguagem para manipular os dados, por exemplo:
Banco de dados Microsoft SQL Server, linguagem: T-SQL (Transact-SQL)
Banco de dados Oracle, linguagem: PL/SQL (Procedural Language/SQL)
Banco de dados MySQL, linguagem: SQL/PSM (SQL/Persistent Stored Module)
Cara linguagem tem modificações implementadas pelo desenvolvedor do banco de dados e essas modificações não são compatíveis entre si. Então, por exemplo, declarar uma variável no SQL SERVER é diferente de fazer a mesma coisa no ORACLE.
NoSQL
“NoSQL” (originalmente “non-SQL” ou “non-relational”) é um termo que define qualquer alternativa aos tradicionais bancos de dados que utilizam SQL.
NoSQL - Banco de dados de documento (document database)
Armazenam os dados em JSON, BSON ou XML. A grande vantagem é que os dados são armazenados em um formato muito parecido com o que a aplicação utiliza, então não é necessário realizar grandes modificações, a aplicação pode simplesmente enviar os dados que está utilizando para serem gravados.
Exemplos de banco de dados de documentos:
MongoDb
CouchDB
Cosmos DB
Couchbase Server
Elasticsearch
NoSQL - Banco chave valor (key-value database ou key value store)
Os dados gravados são associados sem a uma chave única e são sempre armazenados e recuperados utilizando essa chave. São banco de dados muito utilizados por exemplo para cache, como é o caso do Redis.
Exemplos de banco de dados de chave valor:
Redis
memcached
Dynamo (Amazon AWS)
Table Storage (Microsoft Azure)
NoSQL - Banco orientado a colunas (column-oriented database)
//TODO: Complementar
NoSQL - Banco de dados de Grafo (graph database)
//TODO: Complementar
Teorema CAP
Teorema do CAP, também chamado de Teorema de Brewer foi publicado pelo cientista da computação Eric Brewer em 1998, esse teorema afirma que é impossível que o armazenamento de dados distribuído forneça simultaneamente mais de duas das três garantias seguintes:
C (Consistence) Consistência - Todos os clientes veem os mesmos dados ao mesmo tempo, não importa em qual nó eles se conectem. Para que isso aconteça, sempre que os dados forem gravados em um nó, ele deve ser instantaneamente encaminhado ou replicado para todos os outros nós do sistema antes que a gravação seja considerada “bem-sucedida”.
A (Availability) Disponibilidade - Qualquer cliente que fizer uma solicitação de dados obterá uma resposta, mesmo que um ou mais nós estejam desativados. Ou seja, todos os nós em funcionamento no sistema distribuído retornam uma resposta válida para qualquer solicitação, sem exceção.
P (Partition Tolerance) Partição tolerante a falhas - A partição é uma quebra de comunicações dentro de um sistema distribuído, uma conexão perdida ou temporariamente lenta entre dois nós. Tolerância de partição significa que o cluster deve continuar a funcionar mesmo que ocorra uma ou mais falhas de comunicação entre os nós no sistema.
De forma resumida, pensando em um banco de dados com dois nós temos:
Consistência = As informações gravadas no nó 1, também estão no nó 2
Disponibilidade = É possível acessar o nó 1, o nó 2 ou ambos
Tolerância de partição = Um nó é totalmente independente do outro
Não é possível ter as três garantias ao mesmo tempo porque os banco de dados vão estar ligados pela rede e a rede pode falhar.
Na presença de partições, são dadas duas opções: consistência ou disponibilidade. Ao escolher consistência em relação à disponibilidade, o sistema retornará um erro ou um tempo limite se informações específicas não puderem ser garantidamente atualizadas devido à sua partilha na rede. Ao escolher disponibilidade sobre consistência, o sistema sempre processará a consulta e tentará retornar a versão disponível mais recente da informação, mesmo que não possa garantir que ela esteja atualizada devido às partições.
Vamos considerar um exemplo: Em um banco de dados com 2 nós, note que como tempos 2 nós já escolhemos uma das garantias (P - partição), se ao tentar escrever uma informação no nó 1 e a comunicação entre o nó 1 e o nó 2 não estiver disponível:
Se você escolheu um banco de dados com Consistência (P+C), o banco de dados retornará um erro dizendo que não conseguiu concluir a transação e o dado não será gravado em nenhum nó
Se você escolheu um banco de dados com Disponibilidade (P+A), o banco de dados irá gravar somente no nó 1 e somente quando a conexão for restaurada irá gravar no nó 2. Se antes disso acontecer você consultar o nó 2, a informação não estará lá.
Duas considerações importantes:
Como hoje em dia temos sistemas com escada muito grande (muitos usuários simultâneos) normalmente é necessário escolher P (tolerância a partição), então só sobra escolher entre C (Consistence) ou A (Availability)
No exemplo acima estamos temos somente dois nós, isso gera um cenário mais instável, mas imagine que podemos ter um banco de dados com por exemplo 6 nós e solicitar ao banco de dados que aceite a gravação quando conseguir escrever em 2 ou 3 nós.
A consistência conforme definido no teorema de CAP é bastante diferente da consistência garantida em transações de bases de dados ACID (ver abaixo)