不想被 ORM 绑死迁移?dbmate 一个二进制管完 Postgres / MySQL / SQLite / ClickHouse

阅读时长:7分钟

团队里 3 个服务一个用 Go、一个用 Node、一个用 Python,数据库都是 Postgres。每个服务各自带一套框架内置的迁移(Rails / DRF / Sequelize / GORM),同一个 schema 变更要改 3 套不同语法的迁移文件,migrate 命令还各不一样。多人开发 + 生产部署时,“谁先跑了哪个迁移” 就成了一笔糊涂账。

dbmate 是给这种场景准备的解法:一个独立二进制、纯 SQL 迁移文件、不绑任何语言或框架,Postgres / MySQL / SQLite / ClickHouse 共用同一套迁移,跑起来谁先谁后它自己记账。

TL;DR

  • dbmate 是 Go 写的数据库迁移工具,单二进制、零运行时依赖,不绑编程语言和框架。
  • 迁移文件就是纯 SQL,按时间戳命名(如 20260925120000_create_users.up.sql),Git 友好、天然可排序。
  • 支持 PostgreSQL、MySQL、MariaDB、SQLite、ClickHouse,乃至 BigQuery、Spanner。
  • 自带 schema_migrations 表记账 + schema.sql 全量 dump,多环境对账清晰。
  • 适合"多语言服务共享一个库"或"不想被某框架绑死迁移"的场景;单一框架统一管着的团队未必需要。

它和框架内置迁移差在哪?

先把定位说清。Rails / GORM / Django 的迁移是跟着框架走的:你写 Go 就 GORM 的 AutoMigrate / Migrator,写 Python 就 Django 的 migration 文件。优点是生态顺,缺点是语言绑定——换个语言栈迁移方式全变。

dbmate 反过来:语言无关。它只认 SQL。不管你的服务是 Go、Node、Python 还是 PHP,迁移都写同一套 .sql 文件,用同一个二进制跑。

维度 dbmate 框架内置迁移(GORM/Django/Sequelize)
语言绑定 无(纯 SQL) 有(跟框架走)
依赖 单 Go 二进制 依赖框架 + 运行时
跨库 同一套 SQL 多库 多数框架单库/方言差异大
状态记账 schema_migrations 表自管 各框架各表
schema dump 内置生成 schema.sql 多数要另配
适用 多语言混用 / 自架党 单一框架团队

为什么"纯 SQL + 时间戳"是个关键设计

多数迁移工具要么生成难读的语言对象(GORM 的 *gorm.DB 结构体),要么把 SQL 埋在框架里。dbmate 选择把迁移本身当数据:

# 一个迁移就两个文件
migrations/20260925120000_create_orders.up.sql
CREATE TABLE orders (id BIGSERIAL PRIMARY KEY, ...);

migrations/20260925120000_create_orders.down.sql
DROP TABLE orders;
  • 时间戳前缀保证全团队排序一致,不会出现"1、2、3"这种本地相对编号
  • .up / .down 成对,回滚就是跑 .down
  • 纯 SQL 意味着DBA 不用看你代码就能 review 这次 schema 变更,门槛低

它怎么保证多环境不跑偏

两个内置机制让"多个开发者 + 生产"对账清晰:

  • schema_migrations 表:记录每个已跑迁移的版本,启动时自动补齐漏跑的、跳过跑过的。多人各跑各的,合并后跑一次就收敛。
  • schema.sql 全量 dump:每次 run 后导出一份当前 schema 快照。新环境或 CI 直接 psql -f schema.sql 建库,不用从 0 重放所有迁移——这是团队协作里最省时的一个点。

自架党 / 多服务场景,它值不值

适合:

  • 多个微服务共享一个库,语言栈混着(Go + Node + Python)
  • 自架党要一个不绑框架、好审计的 schema 管理工具
  • 生产迁移想要"幂等 + 可回滚 + 有全量快照"这套标准动作
  • 同时管 Postgres 和 ClickHouse(少见但 dbmate 真支持)

不太适合:

  • 整个团队就一个 Django / Rails 应用,框架迁移够用,再引一个 dbmate 是叠床架屋
  • 需要 ORM 层自动生成迁移(如 GORM AutoMigrate 从结构体生成 DDL)——dbmate 不碰 ORM,迁移得手写 SQL

常见问题

Q1: 不写代码、纯 SQL 文件,怎么回滚?

A: 每个迁移有 .up.sql 和 .down.sql 成对文件,dbmate --drop-database 或反向跑 .down 即可。手写 .down 的负担在你,但换来 SQL 的可读和可审计。

Q2: 它能建库 / 删库吗?

A: 能。支持 create-database / drop-database 命令,多环境一键起停。

Q3: 多个服务同时跑 dbmate 会冲突吗?

A: 靠 schema_migrations 表的版本记录收敛。但同一张表被两个服务各写各的迁移,设计上就该归一个服务管——工具解决"跑的顺序",不解决"谁该拥有这张表"。

Q4: 生产迁移中途挂了怎么办?

A: 纯 SQL 默认事务内执行,失败即回滚该迁移,schema_migrations 不记脏版本。大表 DDL(加列 / 索引)建议拆小 + 在线 schema 变更工具配合。

Q5: 和 goose / golang-migrate 比?

A: 都是纯 SQL 路线。dbmate 多支持几个库(ClickHouse / BigQuery / Spanner)、内置 schema dump、能建删库。单一 PG 场景里差异不大,看 CLI 习惯。

Q6: 安装麻烦吗?

A: 单二进制。brew install dbmate(macOS)、scoop install dbmate(Windows)或直接从 GitHub Releases 下对应平台二进制丢进 PATH,dbmate --version 验一下就行。

相关阅读

© 2026 softon.top

本站已稳定运行 267 天 14 小时 · 125 篇文章

使用 Hugo 构建 主题 Stack 由 Jimmy 设计 由 softon 魔改

最近构建时间:2026-09-25 22:27:09 CST