像Git一样管理数据库?我装了Dolt后发现它不只是噱头

阅读时长:12分钟

前言

你有没有过这种经历?

生产环境数据库跑着跑着,一个SQL语句把表结构搞乱了,回滚?对不起,没有备份。想看看上周的数据长什么样?翻日志?可能都找不到。

大多数开发者对代码版本控制驾轻就熟——git commitgit branchgit revert,信手拈来。但对数据库呢?我们通常靠手动导出的 .sql 文件、或者 Flyway/Liquibase 这类迁移工具,处理的是结构变更,不是数据变更

直到我发现了 Dolt。

Dolt 做的事很简单粗暴:把 Git 的版本控制能力,搬到数据库里来了。你可以对数据 branchmergediffcommitrevert——而且它兼容 MySQL 协议,大部分 MySQL 客户端直接就能连。

听起来像科幻小说?我装了之后发现,它确实有真实价值,但也有一些你需要提前知道的坑。

Dolt 到底是什么?

先说结论:Dolt 不是一个"更好的 MySQL"。它是一个带版本控制层的 MySQL 兼容数据库

它的核心思路是把 Git 的分布式版本控制理念引入数据库领域:

  • 每一张表都可以看作一个"仓库"
  • 每一次 COMMIT 都会保存数据的快照
  • 你可以创建分支、合并冲突、回滚到任意历史版本
  • 甚至可以做行级别的 diff——看看某一行数据从周一到周五变了什么

技术实现上,Dolt 底层用的是 Go 语言编写,存储引擎基于 LevelDB 的变体。它不依赖传统的 MySQL 文件系统存储,而是自己管理数据持久化——这意味着它可以在任何能跑 Go 的环境上运行,不只是 Linux。

架构拆解:Git 的 branch/merge 在数据库层怎么实现?

这是我最好奇的部分。代码可以 diff,因为它是文本。但数据库存的是二进制或编码后的行数据,怎么做到 git diff 的效果?

数据存储模型

Dolt 把每张表的数据组织成一种不可变的、版本化的行集合。每次 commit,它不会复制整张表,而是用类似 Git 的"对象存储"方式:

  • 新增的行 → 新建对象
  • 删除的行 → 标记删除
  • 修改的行 → 新旧版本共存,commit 指向新版本

这和 Git 的 blob/tree/commit 对象模型异曲同工。区别在于,Dolt 是在行级别做增量,而不是文件级别。

Branch 的实现

在 Git 中,branch 就是一个指向某个 commit 的指针。Dolt 同理——每个 branch 指向该分支上的最新 commit。你可以在不同 branch 上编辑同一张表的不同数据,互不干扰。

Merge 的难点

这才是真正有意思的部分。两个分支合并时,如果它们修改了同一行数据,怎么办?

Dolt 的做法是:冲突检测 + 手动解决。它会标记出冲突的行,让你决定保留哪一边,或者手动合并。这和 git merge 的行为几乎一致——只是冲突粒度从文件变成了行。

我实测中发现,当两个分支都修改了同一行的多个字段时,Dolt 能精确识别哪些字段冲突了,哪些可以安全合并。这个精细程度出乎意料。

安装与上手实测

环境准备

我用的是 Ubuntu 22.04,Dolt 提供了预编译的二进制包,安装非常简单:

# 下载最新 release
wget https://github.com/dolthub/dolt/releases/latest/download/dolt-linux-amd64.tar.gz
tar -xzf dolt-linux-amd64.tar.gz
sudo cp dolt /usr/local/bin/

# 验证安装
dolt version

初始化仓库

和 Git 一样,Dolt 需要先初始化仓库:

mkdir my-dolt-db
cd my-dolt-db
dolt init

# 启动 Dolt Server
dolt sql-server --user root --password '' --port 3306

启动后,任何 MySQL 客户端都能连接——Navicat、DBeaver、命令行 mysql 都行。

第一次 commit

# 创建表
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(200),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

# 插入数据
INSERT INTO users (name, email) VALUES ('张三', '[email protected]');
INSERT INTO users (name, email) VALUES ('李四', '[email protected]');

# 提交
dolt add .
dolt commit -m "Initial commit: create users table and insert sample data"

注意这里用的是 dolt commit 而不是 COMMIT。Dolt 在标准 SQL 之上扩展了自己的命令体系。

分支操作

# 创建并切换到 feature 分支
dolt branch feature-email-validation
dolt checkout feature-email-validation

# 在分支上添加邮箱验证逻辑
ALTER TABLE users ADD COLUMN email_verified BOOLEAN DEFAULT FALSE;

# 提交
dolt add .
dolt commit -m "Add email verification column"

回到主分支:

dolt checkout main
# 此时看不到 email_verified 列——因为它只在 feature 分支上

和传统方案的对比

vs Flyway / Liquibase

Flyway 和 Liquibase 是业界最主流的数据库迁移工具,但它们解决的是架构变更(schema migration)问题——创建表、加字段、改索引。它们不管数据

Dolt 两者都管。你既可以用它管理表结构变更,也可以追踪每一行数据的变动历史。

维度 Flyway/Liquibase Dolt
管理对象 表结构(schema) 表结构 + 行数据
版本控制 迁移脚本 数据快照
回滚能力 反向迁移脚本 一键 revert 到任意 commit
分支协作 不适用 支持多分支并行开发
冲突检测 行级别冲突
学习曲线 低(SQL 基础即可) 中高(需要理解 Git 概念)

vs PostgreSQL 时间点恢复(PITR)

PostgreSQL 的 PITR 能让你恢复到某个时间点,但它是一个全局级别的操作——整个数据库回滚到那个时刻。你不能"只回滚这张表的这一行"。

Dolt 的优势在于细粒度:你可以精确到某张表、某个 commit、甚至某个分支来回滚。

vs 手动 .sql 备份

说实话,很多中小团队还在用 mysqldump > backup.sql 的方案。简单粗暴,但有几个致命问题:

  1. 你不知道 dump 之间具体差了什么(diff 不了)
  2. 恢复时只能整体恢复,不能局部
  3. 多个开发者各自备份,容易覆盖

Dolt 解决了这些问题,代价是你需要一个新的思维模式。

踩坑记录

坑1:性能差异明显

Dolt 不是 MySQL 的替代品,它在性能上和原生 MySQL 有明显差距。我在测试环境下跑了一个简单的查询benchmark:

  • 原生 MySQL:单表 10 万行数据,简单 SELECT 平均 5ms
  • Dolt:同样的查询,平均 45ms

差了将近 9 倍。原因是 Dolt 在每一层都加了版本控制逻辑——读数据时要解析 commit graph,写数据时要计算 diff。

结论:Dolt 适合读不频繁、写可控的场景。如果你指望用它替代线上 MySQL 做高并发服务,趁早打消这个念头。

坑2:dolt commit 不是 COMMIT

这是一个新手最容易踩的坑。在 Dolt 里:

  • COMMIT —— 提交当前事务(和标准 SQL 一样)
  • dolt commit —— 创建一个版本控制 commit(类似 Git)

很多人以为执行了 COMMIT 就万事大吉了,结果下次 dolt log 一看——什么都没有。数据确实提交了,但没有版本记录。

最佳实践:在 Dolt 里,建议用事务包裹一组操作,然后 dolt commit 一次性提交:

START TRANSACTION;
UPDATE users SET email_verified = TRUE WHERE id = 1;
UPDATE users SET email_verified = TRUE WHERE id = 2;
COMMIT;
dolt commit -m "Verify emails for users 1 and 2";

坑3:Merge 冲突比你想象的频繁

当你同时在两个分支上修改同一张表时,merge 冲突几乎是必然的。特别是当你的业务逻辑涉及跨表关联时——改了 A 表的结构,B 表的 foreign key 约束也跟着报错。

我实测中发现,Dolt 的冲突检测主要针对单表内的行数据,跨表约束的冲突需要你自己处理。这意味着在复杂数据库架构下,merge 的成本会比 Git 高不少。

坑4:备份恢复不是银弹

Dolt 的数据存储在仓库目录下,理论上 cp -r 就是备份。但实际上,Dolt 有自己的备份机制——dolt backup 命令可以把数据推送到远程存储(S3、GCS 等)。

问题是:如果你的仓库目录损坏了,恢复起来比 mysqldump 复杂得多。mysqldump 恢复就是一行命令,Dolt 恢复需要你重建仓库、导入数据、replay commit log。

适用场景判断

经过三天实测,我认为 Dolt 最适合以下场景:

✅ 适合

  1. 数据审计场景:需要追踪"谁在什么时候改了什么数据",Dolt 天然就是为此设计的
  2. 多分支数据开发:比如你在一个分支上做数据清洗,另一个分支跑分析查询,互不干扰
  3. 小规模数据版本管理:几百到几万行的数据集,Dolt 的性能完全可以接受
  4. 学习/实验环境:教学生版本控制概念时,用 Dolt 比用 Git 直观得多——数据看得见摸得着

❌ 不适合

  1. 高并发线上服务:性能差距太大,别折腾
  2. 超大规模数据:百万级以上行的表,Dolt 的 commit/merge 操作会非常慢
  3. 简单 CRUD 应用:如果你的数据库只需要增删改查,没有版本控制需求,原生 MySQL/PostgreSQL 就够了

结语

Dolt 不是要取代 MySQL。它要做的是给数据库加一层 Git

这个想法听起来很浪漫——毕竟我们对 Git 的信任已经根深蒂固了。但现实是,数据库和代码不一样。代码是静态的文本,数据是动态的、有状态的、相互关联的。把 Git 的版本控制模型直接套用在数据上,必然会产生摩擦。

我用了三天,最大的感受是:Dolt 的价值不在于"替代传统数据库",而在于"在传统数据库之上增加一层版本控制"。 它解决的是一个特定的痛点——数据变更追踪——而不是所有数据库问题。

如果你正在为一个需要精细数据版本控制的项目发愁,Dolt 值得一试。如果你只是想找个更快的 MySQL,绕道吧。

最后说一句题外话:技术圈总是热衷于"把 A 的概念搬到 B 上"——Git 搬到数据库、Kubernetes 搬到边缘计算、LLM 搬到嵌入式设备。但真正有价值的创新,往往不是简单的概念移植,而是理解本质后重新设计。Dolt 做到了前者,距离后者还有很长的路。


项目地址https://github.com/dolthub/dolt 官方文档https://docs.dolt.com/ MySQL 兼容客户端:支持 Navicat、DBeaver、HeidiSQL 等主流工具

© 2026 softon.top

本站已稳定运行 263 天 9 小时 · 122 篇文章

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

最近构建时间:2026-09-21 17:06:46 CST