Rust + sqlx:编译期 SQL 校验、连接池与事务管理
test12026-09-122 次阅读
为什么用 sqlx 而不是 ORM
sqlx 是 Rust 的异步 SQL 工具箱,最大卖点是编译期 SQL 校验:在 cargo build 阶段就连接数据库检查你的 SQL 语法和参数数量是否正确,把大量运行时错误提前到编译期。
连接池与编译期校验查询
use sqlx::{PgPool, postgres::PgPoolOptions};
#[derive(sqlx::FromRow)]
struct User {
id: i64,
name: String,
}
async fn init_pool() -> anyhow::Result<PgPool> {
let pool = PgPoolOptions::new()
.max_connections(10)
.connect("postgres://user:pass@localhost/db")
.await?;
Ok(pool)
}
用宏做编译期校验
query_as! 宏会在编译时连库校验 SELECT 字段与结构体是否匹配。离线构建时用 cargo sqlx prepare 生成 .sqlx 缓存,CI 里不必连真实库。
async fn get_user(pool: &PgPool, id: i64) -> anyhow::Result<Option<User>> {
let user = sqlx::query_as!(
User,
"SELECT id, name FROM users WHERE id = $1",
id
)
.fetch_optional(pool)
.await?;
Ok(user)
}
事务保证一致性
转账这类多步写操作必须放进事务。sqlx 的事务 API 与连接池无缝衔接,commit 失败自动回滚。
async fn transfer(pool: &PgPool, from: i64, to: i64, amount: i64) -> anyhow::Result<()> {
let mut tx = pool.begin().await?;
sqlx::query("UPDATE accounts SET balance = balance - $1 WHERE id = $2")
.bind(amount).bind(from)
.execute(&mut *tx).await?;
sqlx::query("UPDATE accounts SET balance = balance + $1 WHERE id = $2")
.bind(amount).bind(to)
.execute(&mut *tx).await?;
tx.commit().await?;
Ok(())
}
要点
- query_as! 在编译期校验 SQL,字段对不上直接编译失败。
- 连接池用 PgPoolOptions 配置上限,避免连接泄漏。
- 多步写操作包进事务,保证原子性。
- 离线 CI 用 cargo sqlx prepare 配合 SQLX_OFFLINE=true。
T
test1
文章作者
为什么用 sqlx 而不是 ORM sqlx 是 Rust 的异步 SQL 工具箱,最大卖点是编译期 SQL 校验:在...
- 分类
- 技术
- 发布时间
- 2026-09-12
- 字数
- 约 1492 字
- 阅读
- 2 次
