Rust 数据库迁移实战:用 sqlx 做版本化迁移与种子数据
test12026-10-2420 次阅读
迁移不该靠手敲 SQL
表结构演进最怕"开发库跑过、生产库没跑"。sqlx 提供编译期校验查询的 migrate 机制,把每一版 schema 变成带序号的文件,启动时自动按序执行,谁的环境漏了迁移都会立刻报错。
组织迁移文件
在 migrations/ 下放带时间戳前缀的 SQL,up 是正向变更,down 用于回滚。
-- migrations/20261024000000_create_users.up.sql
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- migrations/20261024000000_create_users.down.sql
DROP TABLE users;
启动时自动执行迁移
用 sqlx::migrate! 在程序启动阶段把全部 pending 迁移跑完,失败直接 panic 阻止带病启动。
use sqlx::postgres::PgPoolOptions;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let pool = PgPoolOptions::new()
.max_connections(8)
.connect(&std::env::var("DATABASE_URL")?)
.await?;
sqlx::migrate!("./migrations").run(&pool).await?;
println!("迁移完成,服务启动");
Ok(())
}
用嵌入迁移做离线校验
sqlx::query! 宏会在编译期连库校验 SQL 字段,配合 migrate 文件能保证"代码里的查询"和"库里的表"永远对得上。种子数据也可以写成一个迁移:
-- migrations/20261024000100_seed_admin.up.sql
INSERT INTO users (email) VALUES ('admin@example.com')
ON CONFLICT (email) DO NOTHING;
这样新同事 clone 代码、起一个空库、跑服务,表结构和初始数据一次到位,不再有"在我机器上是好的"。
T
test1
文章作者
迁移不该靠手敲 SQL 表结构演进最怕"开发库跑过、生产库没跑"。sqlx 提供编译期校验查询的 migrate 机制...
- 分类
- 技术
- 发布时间
- 2026-10-24
- 字数
- 约 1104 字
- 阅读
- 20 次
