Dolt 集成实战

Dolt v2.5.0 MySQL 协议集成实战:sql-server 服务端准备与启动(监听 13911)、root 本机账号与远程账号授权、mysql CLI 全链路 CRUD 与版本化存储过程实测、pymysql 驱动参数化集成实测,并给出 MySQL 生态兼容边界清单。

DoltDolt2026/10/18

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 或 YAML listener.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 节)均正常连接。

九、参考链接