字数 4407,阅读大约需 13 分钟
Dolt,一个把 MySQL 和 Git 缝在一起的数据库。你在里面建表、插数据、改结构,每一步都能 commit。改错了 reset,想回退 revert,切到任意一个历史 commit 查当时的表数据。开分支做变更,merge 回主干。clone、push、pull,跟 Git 一毛一样。
Git 管文件,Dolt 管表,他们自己挂的口号就是「 Git 和 MySQL 生了个孩子 」。
项目简介 Dolt 是 DoltHub 做的,2019 年到现在一直在迭代。Apache 2.0 开源,GitHub 23.5k star,有商业公司在后面撑着,不是个人开发者在单打独斗,所有稳定性这块应该还是可以的。
二进制 103MB,单文件零依赖,macOS / Linux / Windows 全平台都有。
跟 MySQL 的兼容性做得不错,用什么客户端连上去,写的 SQL 跟 MySQL 没区别。JOIN、外键、触发器、存储过程,该有的都有。它没想做「 更好的 MySQL 」,它做的是 MySQL 缺的东西, 版本控制 。
2026 年 2 月发的 v1.81.10 支持把 GitHub 仓库当远程用,后面细说。Postgres 版 Doltgres 也在做了,现在处于 Beta 阶段,这个版本值得期待。
安装 macOS 一行,Linux 也是一行。
# macOS brew install dolt # Linux sudo bash -c 'curl -L https://github.com/dolthub/dolt/releases/latest/download/install.sh | bash' Windows 下 MSI 安装包或者 choco install dolt 。不想装本机就 Docker:
docker run -p 3306:3306 dolthub/dolt-sql-server:latest 完了 dolt version 看一下,有东西出来就对了。
功能详情 CLI 就是 Git 那套,肌肉记忆全复用 装完 Dolt,终端敲 dolt ,冒出来的命令列表你闭着眼都能认。
dolt init 初始化仓库, dolt add 暂存, dolt commit 提交, dolt log 看记录, dolt diff 看差异, dolt branch 开分支, dolt merge 合并, dolt clone 克隆, dolt push / dolt pull 推拉。连 dolt blame 都有,哪一行谁改的,一个命令出来。
我用过不少号称「 Git-like 」的工具,大部分就是借个概念,命令名像那么回事而已。Dolt 是真的把 Git 的交互模型搬过来了,而且搬得很彻底。 dolt status 看哪些表改过, dolt reset --hard 回退, dolt checkout -b 开新分支,连冲突提示的格式都跟 Git 差不多。你用了十年 Git 的手指头不需要重新学任何东西。
我试的时候跑了个 dolt diff employees ,出来的不是那种 diff 文件的东西,是每一行数据字段级别的变化。哪行加了,哪行删了,哪个字段从啥变啥,清清楚楚。这个感觉怎么说呢,就像你 git diff 代码的时候突然发现它在 diff 你的数据库行。
开个 MySQL 服务,该怎么连怎么连 dolt sql-server 一个命令启动,端口 3306。然后你用 mysql 客户端、TablePlus、Navicat、DataGrip,随便什么连 MySQL 的工具怼上去就行。
还有一个地方比较秀,版本控制的操作不止在 CLI 里有,SQL 里面也能调。每个 CLI 命令都有一个对应的存储过程: call dolt_add() 、 call dolt_commit() 、 call dolt_checkout() 、
call dolt_merge() 、 call dolt_reset() 。
查历史用系统表:
• select * from dolt_log 看 commit 记录 • select * from dolt_diff_employees 看某张表每次改了什么 • select * from dolt_history_employees 看某一行在每个 commit 时的状态 所以你完全可以在应用代码里直接写 SQL 来做版本控制。不需要 SDK,不需要切到命令行,走 MySQL 协议就能搞定。比如某个管理后台想加个「回滚到上个版本」的按钮,一条 call dolt_reset('--hard') 就完事。
Schema 也能分支 改表结构大概是每个 DBA 最烦的事。 ALTER TABLE 上去就下不来了,出问题要么靠备份,要么靠祈祷。一堆人要改同一张表的时候更恶心,排着队等锁,或者互相踩。
Dolt 处理这件事的方式简单粗暴:开个分支上去改,改完 merge。
call dolt_checkout( '-b' , 'add_start_date_column' ); alter table employees add column start_date date ; update employees set start_date = '2018-09-08' ; call dolt_commit( '-am' , 'Added start_date column to employees' ); call dolt_checkout( 'main' ); call dolt_merge( 'add_start_date_column' ); 这六行 SQL 跑完,Schema 变更就合进主干了。如果线上炸了,一个 call dolt_reset('--hard') 回到 merge 之前的状态,半分钟的事。
再想一下这个场景:A 在改 Schema 加字段,B 在往同一个表里改数据。传统数据库里这俩操作要么排队要么打架。Dolt 里 A 在自己分支上改结构,B 在自己分支上改数据,最后先后 merge 进 main,谁也不挡谁。
两个分支改到同一行同一个字段怎么办?Dolt 会报冲突,跟 Git merge conflict 一样,告诉你是哪张表、哪一行、哪个字段、两边各改成了什么。你手动选一个,完事。不是说「表锁了请稍后再试」这种话。
每一格数据的来龙去脉
整过数据治理的人都懂,三个问题能要命:谁改的,什么时候改的,改之前长什么样。
为了答这三个问题,正常做法是:建审计表,写触发器,搭 CDC 管道,或者直接上专门的审计系统。每个方案都是一套独立的维护成本,出问题的时候你要横跳三四个系统排查。
Dolt 把这事做在存储层了。 dolt_history_ 存了每行数据在每个 commit 的完整快照, dolt_diff_ 只保留有变更的 commit。随便你查哪一行哪一个字段,从生到死每一步都看得见,谁在什么时间因为什么原因改的。
落到实际场景里,合规审计这件事约等于白送。SOX 法案要的数据变更追踪,Dolt 开箱就把 log 给你了。 select * from dolt_log 一跑,人、时间、message、commit hash 全在,这堆东西是存在版本链上的,改不了。
顺便说一句, dolt blame 这个命令我特别喜欢,它把「谁改的这行」做到了跟 git blame 一样的体验。你平时用 git blame 追代码变更的那种快感,现在可以用在数据库上了,虽然多数时候追到的是你自己,哈哈。
数据库直接推到 GitHub v1.81.10 加了个功能,让 Dolt 能把 Git 远程仓库当远程用。
你有一个 GitHub 仓库,本来只放代码。现在你 dolt push origin main 一下,数据库也上去了。Dolt 在底层开了个 custom ref 叫 refs/dolt/data ,数据库的东西全塞里面。Git 本身不碰这些东西,你 clone 代码的时候也不会把这个 ref 拉下来,不会多占你本地空间,代码和数据库搁一个仓库里,各过各的。
不用注册 DoltHub,不用配额外远程,只要你本来就有 GitHub,就能把数据库版本化地存上去、拽下来。 dolt clone https://github.com/xxx/yyy.git ,本机就有了。
GitHub Actions 里直接跑数据库 CI:
- name: Clone Dolt database from this GitHub remote run: | dolt clone "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" db - name: Basic sanity checks run: | cd db dolt sql -q "select count(*) as commits from dolt_log;" 每次 push 自动跑一遍:数据库能不能 clone,表结构对不对,commit 记录有没有断,数据库的 CI pipeline 就这么有了。
给 MySQL 挂个版本化副本 Dolt 能当 MySQL 的 binlog 副本使。你的 MySQL 主库一点不动,旁边挂一个 Dolt,它自己消费 binlog,把每笔事务转成 Dolt commit。
主库零侵入,副本默默地攒历史。你在副本上查审计、做分析、甚至恢复误删的数据,主库该怎么跑怎么跑。
数据恢复这个特别实用,有人把线上表删光了,你到 Dolt 副本上 dolt_diff_ 定位到删数据那个 commit,跑一条 dolt diff -r sql ~ > patch.sql
,生成反向 SQL 补丁,往主库上一打,数据回来了。这整个过程主库没停过。相比以前那种「停服、找备份、恢复、祈祷」的流程,简直是降维打击。
Postgres 用户也有份 Doltgres,Dolt 的 PostgreSQL 版本。一条命令装:
sudo bash -c 'curl -L https://github.com/dolthub/doltgresql/releases/latest/download/install.sh | bash' 启动 doltgres , psql 连上去就能用。 dolt_add 、 dolt_commit 、 dolt_checkout 、 dolt_merge ,SQL 接口走存储过程。
目前还没有 Git 风格的 CLI,也还不能推到 DoltHub,但分支合并 diff log 这些核心能力都在。Beta 阶段,写性能大概是原生 Postgres 的 5 倍延迟,读的话看查询类型。追求 PostgreSQL 生态又想要版本控制的话,值得关注后续的版本迭代,目前如果使用PostgreSQL,不建议上。
说两句实话 Dolt 的写性能比原生 MySQL 慢,官方给的数据是 1.1 倍延迟,实际可能不止,这点要有心理准备。如果是纯写密集型而且不需要版本控制,用它属于自找麻烦。读多写少、数据变更频繁、需要审计追溯、或者团队协作改配置数据,这个性能代价值不值还得你考虑好,至少值得一试。
团队推这个东西有阻力是肯定的,用惯 MySQL 的人突然要 call dolt_commit() 才能留痕,习惯得改。好在这个学习成本比学 Git 低太多,毕竟 Git 怎么玩你早就会了。
我说句心里话,Dolt 让我服的不是它技术多牛逼,版本化存储引擎是挺厉害,是开发团队的想法思路,真的不得不服,Git+SQL算是玩出花了。
数据库版本控制这个事,以前都是拼积木:mysqldump 备份,Flyway 管 Schema 迁移,审计表加触发器,binlog 解析管道。每块积木各管各的,出了问题你在四五个地方跳来跳去查。Dolt 把这些全干成一个东西了,commit 一下全有。
冲Dolt这个巧思,我也得给他点个大写的赞!
GitHub仓库:
https://github.com/dolthub/dolt