Uma visão geral de arquivos, bancos de dados e abstrações de armazenamento
Como um programa pode salvar dados?
Um programa pode salvar dados de várias maneiras, mas a forma mais simples é salvar os dados em um arquivo.
Por exemplo, um programa pode salvar os dados em um arquivo de texto(.txt, .csv, .json, etc) ou em um arquivo binário(.dat, .db, .sqlite, etc).
Arquivos de texto são fáceis de ler e editar, mas não são eficientes para armazenar grandes quantidades de dados. Já arquivos binários são mais eficientes, porem são mais difíceis de ler e editar.
Para salvar esses dados, o programa precisa criar um arquivo, escrever os dados no arquivo. Para isso o programa utiliza a API de arquivos do sistema operacional, que fornece funções para criar, abrir, ler, escrever e fechar arquivos.
// C Program to illustrate file opening
#include <stdio.h>
#include <stdlib.h>
int main()
{
// file pointer variable to store the value returned by
// fopen
FILE* fptr;
// opening the file in read mode
fptr = fopen("filename.txt", "r");
// checking if the file is opened successfully
if (fptr == NULL) {
printf("The file is not opened. The program will "
"now exit.");
exit(0);
}
return 0;
}
file = open("data.txt", "w")
file.write("Hello, World!\n")
file.close()
Outra forma de salvar dados é salvar os dados em um banco de dados. Bancos de dados são programas especializados em armazenar e recuperar dados de forma eficiente e segura. Eles possuem uma estrutura organizada que permite a manipulação de dados de forma eficiente e segura.
Entre as principais funções de um banco de dados estão, por exemplo o armazenamento, recuperação, atualização e exclusão de dados, além de controlar o acesso a esses dados.
O que é o Postgres?
Postgres é um sistema de gerenciamento de banco de dados relacional de código aberto. Ele é um dos sistemas de gerenciamento de banco de dados mais avançados e poderosos do mundo. Ele é conhecido por sua confiabilidade, robustez e recursos avançados.
Como o Postgres salva os dados?
Por base todos os dados do Postgres são salvos em um conjunto de arquivos, usando como exemplo um container Docker,
os arquivos serão salvos no diretório /var/lib/postgresql/data
, se fizermos um bind mount para um diretório local,
podemos ver os arquivos que são salvos.
docker run --name some-postgres -e POSTGRES_PASSWORD=mysecre -d -p 5432:5432 -v /tmp/postgres:/var/lib/postgresql/data postgres
ls /tmp/postgres
Como podemos ver, o Postgres salva os dados em um conjunto de arquivos, para fazer um backup dos dados, podemos copiar esses arquivos para outro local.
Caso a instância do Postgres esteja utilizando outro diretório para salvar os dados, podemos verificar o diretório correto executando o comando SHOW data_directory;
no psql.
docker exec -it some-postgres psql -U postgres
SHOW data_directory;
data_directory
----------------
/var/lib/postgresql/data
(1 row)
Analisando a estrutura
- base: Diretório que contém os bancos de dados criados pelo usuário.
| - <oid>: Dentro de `base`, cada diretório com um nome numérico (OID - Object Identifier) representa um banco de dados individual. O OID é um identificador único interno do Postgres.
| | - <oid>: Dentro de cada diretório de banco de dados (`<oid>`), encontramos arquivos nomeados com OIDs que representam tabelas, índices e outros objetos do banco de dados. Estes arquivos contêm os dados propriamente ditos das tabelas e índices.
- global: Diretório que contém dados globais a toda a instância do Postgres, como informações sobre usuários, roles, e bancos de dados (metadados do sistema).
- pg_wal (Write-Ahead Logging): Diretório crucial para a confiabilidade do Postgres. Ele armazena logs de todas as alterações feitas no banco de dados antes que elas sejam efetivamente escritas nos arquivos de dados. Isso garante a durabilidade e a capacidade de recuperação em caso de falhas.
- outros diretórios e arquivos de controle: Existem outros diretórios e arquivos que controlam a configuração, o estado e o funcionamento do servidor Postgres, mas `base`, `global` e `pg_wal` são os mais relevantes para entender o armazenamento de dados.
Para investigar como o Postgres armazena os dados de uma tabela específica, vamos criar um banco de dados chamado test
e, dentro dele, uma tabela chamada test_table
. Inseriremos um registro simples nesta tabela.
CREATE DATABASE test;
\c test
CREATE TABLE test_table (id serial PRIMARY KEY, name VARCHAR(50));
INSERT INTO test_table (name) VALUES ('John');
Para descobrir os OIDs (Object Identifiers) internos do Postgres para o banco de dados test e para a tabela test_table, podemos executar as seguintes consultas SQL:
SELECT oid FROM pg_database WHERE datname = 'test'; -- Busca o OID do banco de dados "test"
SELECT oid FROM pg_class WHERE relname = 'test_table'; -- Busca o OID da tabela "test_table"
Com o OID do banco de dados e da tabela, podemos verificar como o Postgres salva os dados da tabela no arquivo correspondente. Usando o comando hexdump
podemos ver o conteúdo do arquivo.
hexdump -C /tmp/postgres/base/<oid_banco_dados>/<oid_tabela>
Como o Postgres salva os dados em um arquivo binário, o conteúdo do arquivo não é legível, mas podemos ver que os dados estão salvos no arquivo.
A arquitetura de armazenamento do Postgres é muito complexa e vai além do escopo deste artigo, mas podemos ver aonde os dados são salvos e como uma camada de abstração é criada para acessar esses dados.
As camadas de abstração do Postgres, do sistema operacional e outras que se empilham no desenvolvimento de
software modernos são complexas e podemo gerar muitas dúvidas, mas graças a essas camadas que podemos desenvolver software de alta qualidade e confiabilidade em um curto espaço de tempo.