Noções Básicas de Bancos de Dados
10 exemplos para fundamentos de banco de dados em Rust - 7 básicos e 3 intermediários.
Pré-requisitos
[dependencies]
sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "macros"] }
tokio = { version = "1", features = ["full"] }- sqlx 0.8 fornece acesso assíncrono ao PostgreSQL com verificação opcional de consultas em tempo de compilação.
- Defina
DATABASE_URLpara desenvolvimento local.
Exemplos Básicos
1. Conectar com sqlx
Abra uma única conexão para scripts.
let conn = sqlx::PgConnection::connect(&std::env::var("DATABASE_URL")?).await?;PgConnectioné uma única conexão, não um pool.- Prefira pools para servidores.
- Formato da string de conexão:
postgres://user:pass@host/db.
Relacionado: sqlx - Guia completo do sqlx
2. Pool de Conexões
Compartilhe conexões entre tarefas assíncronas.
let pool = sqlx::postgres::PgPoolOptions::new()
.max_connections(10)
.connect(&database_url)
.await?;- O pool distribui conexões e as retorna quando terminadas.
- Dimensionamento com base nos workers da CPU e
max_connectionsdo DB. - Clone
PgPoolde forma barata -Arcinterno.
Relacionado: Pool de Conexões - Orientações de dimensionamento
3. Consulta Parametrizada
Previna injeção de SQL.
let row: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM users WHERE active = $1")
.bind(true)
.fetch_one(&pool)
.await?;- Sempre use placeholders
$1, nunca formate strings. query_asmapeia colunas para tupla ou struct.- Erros são
sqlx::Error.
4. Inserir Retornando
Obtenha IDs gerados do PostgreSQL.
let rec: (i64,) = sqlx::query_as(
"INSERT INTO items (name) VALUES ($1) RETURNING id"
)
.bind("widget")
.fetch_one(&pool)
.await?;RETURNINGevita uma segunda viagem de ida e volta.- Funciona com
query_scalarpara valores únicos.
5. Buscar Linha Opcional
Lide com linhas ausentes sem erro.
let user = sqlx::query_as::<_, User>("SELECT id, email FROM users WHERE id = $1")
.bind(id)
.fetch_optional(&pool)
.await?;fetch_optionalretornaOption<Row>.- Mapeie
Nonepara 404 em manipuladores HTTP.
6. Migrações na Inicialização
Aplique o esquema antes de servir tráfego.
sqlx::migrate!("./migrations").run(&pool).await?;- Arquivos SQL no diretório
migrations/. - Nomes de arquivo versionados com timestamps.
- Execute também em CI e pipeline de implantação.
Relacionado: Migrações - Evolução do esquema
7. Encerramento Gracioso do Pool
Feche o pool ao sinal de encerramento.
pool.close().await;- Aguarda a conclusão das consultas em andamento (com timeout).
- Emparelhe com o encerramento gracioso do Axum.
Exemplos Intermediários
8. Bloco de Transação
Atualizações atômicas de várias instruções.
let mut tx = pool.begin().await?;
sqlx::query("UPDATE accounts SET balance = balance - $1 WHERE id = $2")
.bind(100_i64).bind(1_i64).execute(&mut *tx).await?;
sqlx::query("UPDATE accounts SET balance = balance + $1 WHERE id = $2")
.bind(100_i64).bind(2_i64).execute(&mut *tx).await?;
tx.commit().await?;rollbackocorre automaticamente ao cair com?sem commit.- Mantenha as transações curtas.
Relacionado: Transações e Isolamento - Níveis de isolamento
9. Armazenar Pool no Estado do Axum
Integre o banco de dados ao serviço HTTP.
#[derive(Clone)]
struct AppState { pool: sqlx::PgPool }
let state = AppState { pool: pool.clone() };
let app = Router::new().route("/users", get(list_users)).with_state(state);PgPoolé Clone barato.- Um pool por processo, tipicamente.
Relacionado: Extratores e Estado - Estado do Axum
10. Consulta de Verificação de Integridade
Verifique a conectividade do DB para /ready.
sqlx::query("SELECT 1").fetch_one(&pool).await?;- Sonda leve para orquestradores.
- Distinga
/health(processo ativo) de/ready(DB ativo).
Versões da Stack: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4 e Polars 0.46+.