Dolt 集成实战
Dolt v2.5.0 MySQL 协议集成实战:sql-server 服务端准备与启动(监听 13911)、root 本机账号与远程账号授权、mysql CLI 全链路 CRUD 与版本化存储过程实测、pymysql 驱动参数化集成实测,并给出 MySQL 生态兼容边界清单。
Dolt 集成实战
> 目标:验证 Dolt 的 MySQL 生态兼容性——用 mysql CLI 与 Python pymysql 驱动直连 dolt sql-server 完成 CRUD、事务与版本化存储过程调用,并给出实测得到的兼容边界;全部命令与回显在 Ubuntu 22.04 LTS + Dolt v2.5.0 + MySQL 客户端 8.0.46 真实环境跑通,服务端部署见《Dolt 安装部署指南》,版本化语法见《Dolt 版本化 SQL 实战》。
一、环境信息
本文所有命令与回显所依赖的实测环境:
- 操作系统:Ubuntu 22.04 LTS(x86_64)
- 服务端:Dolt v2.5.0(
dolt sql-server,监听0.0.0.0:13911,默认端口为 3306,本文用 13911 演示自定义端口) - 服务端数据目录:
/opt/data/dolt/server1,含两个数据库仓库:shopdb(orders 表)、appdb(kv 表) - 客户端:mysql CLI(
mysql Ver 8.0.46-0ubuntu0.22.04.4)、Python 3.10.12 + pymysql 2.2.8 - 演示账号:
root(服务端自动创建的本机账号)与admin/q1w2e3r4(远程演示账号)
二、前置条件
2.1 准备服务端数据目录
一个 sql-server 以其工作目录下的每个 dolt 仓库子目录为一个 database。初始化两个库(每个子目录各自 dolt init):
mkdir -p /opt/data/dolt/server1/shopdb /opt/data/dolt/server1/appdb
cd /opt/data/dolt/server1/shopdb
dolt init
dolt sql -q 'create table orders (id int primary key, product_id int, amount decimal(10,2), created_at datetime default current_timestamp); insert into orders values (1,1,199.00,"2026-10-18 10:00:00"),(2,2,89.50,"2026-10-18 10:05:00"); call dolt_add("-A"); call dolt_commit("-m","orders 初始化")'
cd ../appdb
dolt init
dolt sql -q 'create table kv (k varchar(64) primary key, v varchar(255)); insert into kv values ("mode","test"); call dolt_add("-A"); call dolt_commit("-m","kv 初始化")'
实测回显(shopdb 初始化,appdb 同构):
Successfully initialized dolt data repository.
+--------+
| status |
+--------+
| 0 |
+--------+
+----------------------------------+
| hash |
+----------------------------------+
| fe1i750gf7i6ona163qu18baa24pt41v |
+----------------------------------+
2.2 启动服务并确认监听
cd /opt/data/dolt/server1
nohup dolt sql-server -H 0.0.0.0 -P 13911 -l info > /opt/data/dolt/server1/server.log 2>&1 &
sleep 3
ss -tlnp | grep 13911
tail -4 server.log
实测回显:
LISTEN 0 4096 *:13911 *:* users:(("dolt",pid=1766847,fd=18))
time="2026-10-18T11:15:12+08:00" level=info msg="Creating root@localhost superuser"
time="2026-10-18T11:15:12+08:00" level=info msg="Server ready. Accepting connections."
time="2026-10-18T11:15:12+08:00" level=warning msg="secure_file_priv is set to \"\", which is insecure."
💡 说明:首次启动自动创建
root@localhost超级用户(无密码、仅本机);secure_file_priv告警提示默认允许任意文件读写路径,生产环境建议在 YAML 配置里收紧(完整配置字段见《Dolt 安装部署指南》Q6)。常驻服务建议改用 systemd 托管(同篇实测配方)。
三、连接与认证
3.1 本机 root 直连
mysql -h 127.0.0.1 -P 13911 -u root -e "show databases"
mysql -h 127.0.0.1 -P 13911 -u root -e "select version()"
实测回显:
Database
appdb
information_schema
mysql
shopdb
version()
8.0.31
show databases 中 shopdb/appdb 就是数据目录下的两个子目录;select version() 返回 8.0.31 是 Dolt 兼容层对外声称的 MySQL 版本号(与实际安装的 MySQL 服务器版本无关)。
3.2 远程账号(root 默认不能远程)
尝试从其他主机以 root 连接会失败:
ERROR 1045 (28000): Access denied for user 'root'
创建可远程连接的演示账号并授权:
mysql -h 127.0.0.1 -P 13911 -u root -e "create user 'admin'@'%' identified by 'q1w2e3r4'; grant all privileges on *.* to 'admin'@'%'; select user, host from mysql.user"
实测回显:
user host
__dolt_local_user__ localhost
admin %
event_scheduler localhost
root localhost
远程验证(从另一台主机连本机 IP):
mysql -h <服务器IP> -P 13911 -u admin -pq1w2e3r4 -e "show databases"
实测回显:
Database
information_schema
mysql
shopdb
⚠️ 注意:
__dolt_local_user__为服务端内置本机账号,勿动;'admin'@'%'对所有来源开放,生产环境应收敛来源网段并定期轮换口令。
四、mysql CLI 集成实测
4.1 查询与 CRUD
mysql -h 127.0.0.1 -P 13911 -u root shopdb -e "select id, product_id, amount, created_at from orders"
mysql -h 127.0.0.1 -P 13911 -u root shopdb -e "insert into orders (id, product_id, amount) values (3, 1, 159.20); update orders set amount=79.00 where id=2; select id, amount from orders"
实测回显:
id product_id amount created_at
1 1 199.00 2026-10-18 10:00:00
2 2 89.50 2026-10-18 10:05:00
id amount
1 199.00
2 79.00
3 159.20
INSERT/UPDATE/SELECT 全部走 MySQL wire protocol 正常工作,datetime/decimal 类型原样返回。
4.2 协议内调用版本化存储过程
这是 Dolt 集成的独有卖点:MySQL 客户端可以直接驱动数据版本操作。
mysql -h 127.0.0.1 -P 13911 -u root shopdb -e "call dolt_add('-A'); call dolt_commit('-m', 'MySQL 协议写入:新增订单3,调整订单2'); select active_branch()"
实测回显:
+----------------------------------+
| hash |
+----------------------------------+
| blhavfj1qhibh2a3lvg349keef9ccfu4 |
+----------------------------------+
active_branch()
main
提交后用 AS OF 对比写入前后(版本化语法经协议同样可用):
mysql -h 127.0.0.1 -P 13911 -u root shopdb -e "select id, amount from orders as of 'main~1' where id in (1,2)"
实测回显:
id amount
1 199.00
2 89.50
main~1(上一提交)里 id=2 还是原值 89.50,当前值已是 79.00——协议客户端完成了一次完整的时间旅行查询。
4.3 事务
mysql -h 127.0.0.1 -P 13911 -u root shopdb <<'EOF'
start transaction;
insert into orders (id, product_id, amount) values (9, 9, 9.00);
rollback;
select id from orders where id=9;
EOF
实测回显(rollback 后无 id=9,空结果):
select id from orders where id=9
START TRANSACTION/COMMIT/ROLLBACK 语义与 MySQL 一致。> 💡 说明:Dolt 默认 dolt_transaction_commit=0——SQL 事务的 commit 不自动产生 Dolt 版本提交,只有 call dolt_commit(...) 才落版本;把 YAML 配置 behavior.dolt_transaction_commit 设为 true 可让每个事务自动成版本(适合想让普通应用「无感知版本化」的场景)。
五、Python pymysql 驱动集成实测
5.1 安装与连接
pip3 install pymysql
实测回显(版本确认):
pymysql 2.2.8
5.2 参数化 CRUD + 版本化提交
import pymysql
conn = pymysql.connect(host='127.0.0.1', port=13911, user='root', database='shopdb')
cur = conn.cursor()
cur.execute("select id, product_id, amount from orders order by id")
print("pymysql 查询:", cur.fetchall())
cur.execute("insert into orders (id, product_id, amount) values (%s, %s, %s)", (4, 3, 1299.00))
conn.commit()
cur.execute("call dolt_add('-A')")
cur.execute("call dolt_commit('-m', %s)", ("pymysql 写入订单 4",))
print("提交哈希:", cur.fetchall())
cur.execute("select id, amount from orders where id=4")
print("确认写入:", cur.fetchall())
cur.close(); conn.close()
实测输出:
pymysql 查询: ((1, 1, Decimal('199.00')), (2, 2, Decimal('79.00')), (3, 1, Decimal('159.20')))
提交哈希: (('qs7m3os5e12u7i9a68h2gj05923mv3qf',),)
确认写入: ((4, Decimal('1299.00')),)
实测要点:
- 标准参数化占位
%s、Decimal类型映射、conn.commit()事务提交全部正常; call dolt_commit('-m', %s)支持把提交消息作为参数绑定——应用可以把「业务上下文」拼进版本消息,实现应用级数据审计;- 其他常见驱动(Go 的 go-sql-driver/mysql、Java 的 Connector/J、各语言 ORM 的 MySQL 方言)走同一协议,行为可预期,但 Dolt 未实现的 SQL 会报错(见第六节边界)。
六、MySQL 生态兼容边界(实测清单)
以下边界全部在本环境实测确认:
| 能力 | 实测结果 | 说明 |
|---|---|---|
| MySQL wire protocol | ✅ 兼容 | mysql 8.0 CLI 与 pymysql 直连无障碍 |
| DDL/DML(表、行、类型) | ✅ 兼容 | int/varchar/decimal/datetime 实测正常 |
| 事务 ACID(单机) | ✅ 兼容 | start transaction/rollback 实测正常 |
| information_schema | ✅ 基本可用 | information_schema.tables 可查(实测查到 orders) |
| SHOW VARIABLES | ⚠️ 有偏差 | 实测 max_connections 返回 151(MySQL 默认值),而 Dolt 监听器默认 max_connections 为 1000——变量表未必反映服务端真实生效值 |
| version() | ⚠️ 固定 8.0.31 | 兼容层声明值,不代表真实 MySQL 版本 |
| root 账号模型 | ⚠️ 差异 | 自动创建 root@localhost 无密码仅本机;无 MySQL 的 caching_sha2_password 等认证插件概念 |
| 存储过程定义(CREATE PROCEDURE) | ⚠️ 子集 | Dolt 支持调用其内置 DOLT_* 过程;用户自定义存储过程支持与 MySQL 语法有差异,需逐项验证 |
| 复制/组复制 | ❌ 不适用 | 无 MySQL 主从/组复制形态;分布式协作走 dolt remote push/pull |
| 高并发 OLTP 吞吐 | ⚠️ 低于原生 MySQL | 版本化写入开销所致,见《Dolt 介绍与选型指南》 |
结论:把 Dolt 当「MySQL 方言的单机版本化数据库」接入现有 MySQL 客户端/工具链是顺畅的;依赖高级特性(复制、完整优化器行为、全部系统变量语义)时必须逐项实测。
七、注意事项
- 端口默认 3306:与 MySQL 同端口,同机部署注意冲突,用
-P 13911或 YAMLlistener.port改口; - root 无密码仅本机:远程一律显式建号(见第三节),并通过防火墙限制 13911 暴露面;
- 数据目录即数据库:server 工作目录下的子目录名就是库名,目录改名/移动会改变对外库名;
- 版本提交需显式触发:普通 DML 只改工作区,不产生版本提交;只有
call dolt_commit(...)或dolt_transaction_commit=true时才落版本,集成应用需明确自己的提交策略; - 备份:停服或低峰期直接复制仓库目录即可(内容寻址存储天然一致),或用
dolt backup/dolt push到远端。
八、常见问题
Q1:连接报 ERROR 1045 (28000): Access denied for user 'root'?
root 只允许本机无密码连接。本机请确认 -h 127.0.0.1;远程请按 3.2 节创建 'admin'@'%' 类账号。
Q2:pymysql/驱动里执行 call dolt_commit(...) 返回什么结构?
单行单列 hash 结果集(见 5.2 实测输出);dolt_merge 返回 hash/fast_forward/conflicts/message 四列,程序可据此判断合并结果(见《Dolt 版本化 SQL 实战》4.2)。
Q3:ORM 框架能直接用吗? 连接层无障碍(协议兼容);建议把 dialect 配为 MySQL。但 ORM 迁移工具生成的 DDL 里若用到 Dolt 未实现的特性(部分存储引擎选项、全文索引语法等)会报错,先在开发库全量跑一遍迁移脚本验证。
Q4:一个 server 能承载多少库?
工作目录下每个 dolt 仓库子目录都是一个库,数量无硬限制;每库独立提交图。切换库即 USE shopdb,与 MySQL 相同。
Q5:select version() 显示 8.0.31 但我客户端是 8.4,会有问题吗?
无碍——version() 是服务端兼容层声称值,客户端与服务端版本无强绑定;实测 mysql 8.0.46 客户端(本篇)与 8.4 客户端(《Dolt 安装部署指南》8.5 节)均正常连接。