SeaORM Migrator CLI 迁移命令完全指南生成、应用、回滚与状态管理实战【免费下载链接】sea-orm A powerful relational ORM for Rust项目地址: https://gitcode.com/gh_mirrors/se/sea-orm导读本文以 examples/loco_example/migration/README.md 为骨架系统讲解 SeaORM 生态中sea-orm-migration提供的一整套数据库迁移命令行操作从生成迁移文件、应用待执行迁移、按数量回滚到fresh、refresh、reset、status等生命周期管理命令。阅读本文后你将能够在任何以sea-orm-migration为迁移层的 Rust 项目中熟练驾驭 Migrator CLI并理解每条命令背后对应的底层MigratorTrait调用链真正做到「知其然也知其所以然」。一、迁移工程的基本构成CLI 从哪里来在 examples/loco_example/migration 示例工程中迁移被组织为一个独立的 Cargo crate它由三个核心文件组成src/lib.rs定义Migrator结构体实现MigratorTrait并通过migrations()方法把工程内所有迁移文件注册进一个列表src/main.rs二进制入口调用cli::run_cli(migration::Migrator)启动命令行Cargo.toml声明对sea-orm-migration的依赖。其中Cargo.toml有一个关键点值得注意sea-orm-migration需要显式启用至少一个ASYNC_RUNTIME与DATABASE_DRIVER特性才能在 CLI 中执行迁移示例中使用的是[dependencies.sea-orm-migration] features [ runtime-tokio-rustls, # ASYNC_RUNTIME feature ] version ~2.0.3 # sea-orm-migration version从源码结构看main.rs调用的cli::run_cli位于 sea-orm-migration/src/cli.rs它先读取.envdotenv().ok()再用 clap 解析命令行参数然后从DATABASE_URL环境变量或--database-url/-u参数构造ConnectOptions建立数据库连接最后把解析出的子命令分发给MigratorTrait对应方法。这意味着所有迁移命令都必须在能连接到目标数据库的前提下运行。二、命令总览原文档提供的命令可汇总为下表这是迁移工作流中最常用的九种操作命令作用是否需要连接数据库migrate generate MIGRATION_NAME生成一个新的迁移文件否仅写文件cargo run无参数应用所有待执行的迁移是cargo run -- up应用所有待执行的迁移是cargo run -- up -n 10应用前 10 个待执行的迁移是cargo run -- down回滚最近一次应用的迁移是cargo run -- down -n 10回滚最近 10 次应用的迁移是cargo run -- fresh删除数据库所有表再重新应用全部迁移是cargo run -- refresh回滚全部已应用迁移再重新应用全部迁移是cargo run -- reset回滚全部已应用迁移是cargo run -- status查看所有迁移的执行状态是这些子命令在 sea-orm-cli/src/cli.rs 中被定义为MigrateSubcommands枚举每个变体都带上了面向用户的about描述例如Fresh的说明是 Drop all tables from the database, then reapply all migrationsStatus的说明是 Check the status of all migrations与文档语义完全一致。说明cargo run会先编译并运行迁移 crate 的二进制即main.rs--之后的部分才会作为参数传给程序本体。因此 README 中的cargo run -- up、cargo run -- status等写法本质是把up、status等子命令交给cli::run_cli解析。三、生成新迁移文件cargo run -- migrate generate MIGRATION_NAME该命令不需要数据库连接它的职责是在迁移目录下创建一个新的、空白的迁移文件。执行流程对应 sea-orm-migration/src/cli.rs 中的run_non_db_command当解析到Generate子命令时调用run_migrate_generate直接生成文件并提前返回跳过数据库连接步骤。从 MigrateSubcommands::Generate 的定义可以得知该子命令还支持两个可选参数--universal-time默认true按 UTC 时间生成迁移文件名的时间戳前缀--local-time按本地时间生成时间戳与--universal-time互斥。生成的迁移文件遵循 SeaORM 的时间戳 名称命名约定如m20231103_114510_notes并预置up/down方法的骨架开发者只需在其中填充具体的表结构变更逻辑。四、应用迁移up与无参数运行cargo run cargo run -- up cargo run -- up -n 10三条命令都用于应用迁移区别在于应用的数量不带子命令的cargo run与cargo run -- up行为一致应用所有待执行的迁移cargo run -- up -n 10只应用前10个待执行的迁移-n即--num类型为Optionu32。从 run_migrate_inner 的匹配逻辑可以看到默认行为的设计Up { num }子命令调用migrator.up(db, num)而未解析到任何子命令_分支时同样落到migrator.up(db, None)即「无参数 全部应用」这正是 README 中cargo run与cargo run -- up等价的原因。SeaORM 通过seaql_migrations表记录每一条迁移的应用状态up只会执行尚未被标记为已应用的迁移因此重复运行是安全的——未新增迁移时直接提示无待执行项。这一点在 examples/loco_example/README.md 的运行日志中也有印证INFO sea_orm_migration::migrator: Applying all pending migrations INFO sea_orm_migration::migrator: No pending migrations五、回滚迁移downcargo run -- down cargo run -- down -n 10down负责回滚已应用的迁移cargo run -- down回滚最近一次应用的迁移cargo run -- down -n 10回滚最近10次应用的迁移。注意与up的区别Down子命令的num参数默认值为1见 MigrateSubcommands::Down 中default_value 1的定义所以省略-n时恰好回滚一次而Up的num是Optionu32缺省即None语义为「全部」。底层实现上down调用的是migrator.down(db, Some(num))会按应用顺序的逆序执行各迁移文件中的down方法。六、全量重建三兄弟fresh、refresh、reset这三条命令都涉及全部迁移的重置但破坏程度和流程截然不同是日常开发中容易混淆、也最容易误操作的一组命令cargo run -- fresh cargo run -- refresh cargo run -- reset命令流程数据影响fresh直接删除数据库中所有表然后重新应用全部迁移破坏性最强表内数据全部丢失refresh先回滚全部已应用迁移逐个执行down再重新应用全部迁移回滚阶段会执行down逻辑若down只删表数据同样会丢失reset只回滚全部已应用迁移不重新应用回滚后数据库停留在无迁移表状态seaql_migrations记录也会被清理这三条命令在 run_migrate_inner 中分别映射为migrator.fresh(db)、migrator.refresh(db)、migrator.reset(db)。从 SeaORM 的惯例来看fresh/reset属于破坏性操作建议只在开发或测试环境使用——这一点在 Loco 的配置文件中也有对应体现见下文第八节。如果只想清空数据但保留表结构应使用truncate类操作而不是这三条命令。七、查看迁移状态statuscargo run -- statusstatus会列出所有已注册的迁移并标注每条迁移当前是「已应用」还是「待应用」用于排查为什么某次up没有执行新的迁移可能对应迁移已被标记为已应用数据库结构与迁移历史是否一致reset/down之后还有哪些迁移处于待应用状态。在 run_migrate_inner 中它对应migrator.status(db)。status只读不写是三者中最安全、最适合日常巡检的命令。八、全局参数与环境变量除子命令外Migrator CLI 还提供三个全局参数它们在 sea-orm-migration/src/cli.rs 的Cli结构体中定义参数短选项环境变量说明--database-url-uDATABASE_URL数据库连接 URL未提供时读取环境变量--database-schema-sDATABASE_SCHEMA数据库 schema仅 PostgreSQL 有效默认publicMySQL 与 SQLite 忽略--verbose-v—输出 debug 级别日志默认仅显示sea_orm_migration的 info 日志其中DATABASE_URL是必需项——run_cli_with_connection 中会执行expect(Environment variable DATABASE_URL not set)也就是说若不通过-u传入 URL就必须在环境或.env文件中提供DATABASE_URL否则 CLI 会直接报错退出。在 Loco 示例中数据库连接信息统一配置在 config/development.yamldatabase: # Database connection URI uri: postgres://loco:locolocalhost:5432/loco_app enable_logging: false connect_timeout: 500 idle_timeout: 500 min_connections: 1 max_connections: 1 # Run migration up when application loaded auto_migrate: true # Truncate database when application loaded. This is a dangerous operation, make sure that you using this flag only on dev environments or test mode dangerously_truncate: false # Recreating schema when application loaded. This is a dangerous operation, make sure that you using this flag only on dev environments or test mode dangerously_recreate: false其中auto_migrate: true表示应用启动时自动执行「应用全部待迁移」即up这就是 examples/loco_example/README.md 启动日志中 auto migrating 的来源而dangerously_truncate、dangerously_recreate则对应上面提到的fresh/reset类破坏性操作的安全开关仅在开发/测试环境启用。也就是说在 Loco 应用中日常迁移交给auto_migrate自动完成而cargo run -- migrate ...这类 CLI 命令更多用于显式生成迁移、修复迁移历史或做全量重建。九、迁移文件示例up/down如何被 CLI 驱动理解 CLI 命令之后再来看命令实际驱动的最小执行单元——迁移文件。以示例工程中的 src/m20231103_114510_notes.rs 为例use sea_orm_migration::{prelude::*, schema::*}; #[derive(DeriveMigrationName)] pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(self, manager: SchemaManager) - Result(), DbErr { manager .create_table( table_auto(notes) .col(pk_auto(id)) .col(string_null(title)) .col(string_null(content)) .to_owned(), ) .await } async fn down(self, manager: SchemaManager) - Result(), DbErr { manager .drop_table(Table::drop().table(notes).to_owned()) .await } }这段代码揭示了三层对应关系up方法负责正向变更建表down方法负责逆向变更删表up/down命令正是按此语义逐个调用对应方法#[derive(DeriveMigrationName)]让迁移名称与结构体名绑定m20231103_114510_notes这也是status命令能展示迁移名称的依据每个迁移实例通过 src/lib.rs 中Migrator::migrations()的vec![Box::new(...)]注册进迁移列表CLI 的up/down/status等命令都以这份注册表为准进行调度。当新增迁移文件后需要同步把它注册到migrations()列表中cargo run -- migrate generate生成的骨架文件正是为了配合这个注册流程减少手工建文件的成本。十、常见工作流与注意事项基于上面的命令语义可以归纳出几条典型的日常工作流开发一个新表结构cargo run -- migrate generate create_xxx→ 在生成的up/down中编写建表/删表逻辑 → 注册进migrations()→cargo run -- up或直接重启应用触发auto_migrate。本地反复调整表结构cargo run -- down回滚上一次迁移 → 修改迁移代码 →cargo run -- up重新应用。完全重置开发库cargo run -- fresh确认数据可丢或cargo run -- refresh走一遍downup完整流程。排查迁移不一致cargo run -- status对比迁移历史与seaql_migrations记录。使用注意事项fresh/reset/refresh是破坏性命令执行前务必确认目标库不是生产环境DATABASE_URL必须可通过-u参数或环境变量获得否则所有需要连接数据库的命令都会失败down -n的回滚数量默认是 1而up -n缺省表示全部二者默认语义不同写脚本时不要混用若工程通过[patch.crates-io]指向本仓库源码如 examples/loco_example/Cargo.toml 所示命令行为与发布版一致可放心对照本文学习源码。结语Migrator CLI 是 SeaORM 迁移体系的操作入口generate负责产生迁移up/down负责步进式的应用与回滚fresh/refresh/reset负责全量重建status负责可观测性。本文以 examples/loco_example/migration/README.md 为主线、以 sea-orm-migration/src/cli.rs 与 sea-orm-cli/src/cli.rs 的源码为佐证完整还原了每条命令从输入到MigratorTrait方法调用的全链路。掌握这套命令后无论是手动管理迁移历史还是结合 Loco 的auto_migrate自动化启动迁移都能做到胸有成竹。【免费下载链接】sea-orm A powerful relational ORM for Rust项目地址: https://gitcode.com/gh_mirrors/se/sea-orm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
