> [!NOTE] > 本文档由 WeHub 基于上游 README 翻译整理,属于社区翻译,非官方中文文档。 > [English](./README.en.md) · [原始项目](https://github.com/dolthub/dolt) · [上游 README](https://github.com/dolthub/dolt/blob/HEAD/README.md) > 原作者、版权与许可证归属以原始项目及本仓库 LICENSE 文件为准。 # Dolt 是数据的 Git! Dolt 是一款 SQL 数据库,你可以像操作 Git 仓库一样对它进行 fork、clone、branch、merge、push 和 pull。 像连接任何 MySQL 数据库一样连接 Dolt,即可读取或修改 schema 和数据。版本控制功能通过 SQL 中的系统表、函数和存储过程暴露出来。 或者,使用类似 Git 的命令行界面导入 CSV 文件、提交更改、推送到远程,或合并队友的更改。你熟悉的所有 Git 命令在 Dolt 中用法完全相同。 Git 对文件进行版本控制。Dolt 对表进行版本控制。它就像 Git 和 MySQL 的结合体。 我们还构建了 [DoltHub](https://www.dolthub.com),,一个分享 Dolt 数据库的平台。我们免费托管公开数据。如果你想自行托管 DoltHub,我们有 [DoltLab](https://www.doltlab.com).。如果你想让我们为你运行 Dolt 服务器,我们有 [Hosted Dolt](https://hosted.doltdb.com).。 更喜欢 Postgres 而不是 MySQL?试试 [Doltgres](https://github.com/dolthub/doltgresql),,目前已进入 Beta 版本。 [加入我们的 Discord](https://discord.com/invite/RFwfYpu)打个招呼、提问,或[查看我们的路线图](https://dolthub.com/docs/other/roadmap),了解我们接下来要构建什么。 # 视频介绍 [![Dolt Explainer Video](https://img.youtube.com/vi/H2iZy0Cme10/maxresdefault.jpg)](https://www.youtube.com/watch?v=H2iZy0Cme10) # 它有什么用? 用途很多!Dolt 是一款通用工具,应用场景数不胜数。但如果你想找些灵感,[可以看看人们目前是如何使用它的](https://dolthub.com/blog/2024-10-15-dolt-use-cases/).。 Dolt 为 [Beads](https://github.com/gastownhall/beads) 和 [Gas Town](https://github.com/steveyegge/gastown). 提供支持。它是智能体记忆(agent memory)的最佳数据库,尤其是在你迈向多智能体、多机器工作流时。 # Dolt CLI `dolt` CLI 拥有与 `git` 相同的命令,并附带一些额外功能。 ``` $ dolt Valid commands for dolt are init - Create an empty Dolt data repository. status - Show the working tree status. add - Add table changes to the list of staged table changes. diff - Diff a table. reset - Remove table changes from the list of staged table changes. clean - Remove untracked tables from working set. commit - Record changes to the repository. sql - Run a SQL query against tables in repository. sql-server - Start a MySQL-compatible server. log - Show commit logs. branch - Create, list, edit, delete branches. checkout - Checkout a branch or overwrite a table from HEAD. merge - Merge a branch. conflicts - Commands for viewing and resolving merge conflicts. cherry-pick - Apply the changes introduced by an existing commit. revert - Undo the changes introduced in a commit. clone - Clone from a remote data repository. fetch - Update the database from a remote data repository. pull - Fetch from a dolt remote data repository and merge. push - Push to a dolt remote. config - Dolt configuration. remote - Manage set of tracked repositories. backup - Manage a set of server backups. login - Login to a dolt remote host. creds - Commands for managing credentials. ls - List tables in the working set. schema - Commands for showing and importing table schemas. table - Commands for copying, renaming, deleting, and exporting tables. tag - Create, list, delete tags. blame - Show what revision and author last modified each row of a table. constraints - Commands for handling constraints. migrate - Executes a database migration to use the latest Dolt data format. read-tables - Fetch table(s) at a specific commit into a new dolt repo gc - Cleans up unreferenced data from the repository. filter-branch - Edits the commit history using the provided query. merge-base - Find the common ancestor of two commits. version - Displays the current Dolt cli version. dump - Export all tables in the working set into a file. ``` # 安装 Dolt 是一个约 103 MB 的单一程序。 ```bash dolt $ du -h /Users/timsehn/go/bin/dolt 103M /Users/timsehn/go/bin/dolt ``` 安装非常简单。下载后放到你的 `PATH` 上即可。我们还为大多数平台提供了多种更便捷的方式。 ## 从最新版本安装 要在基于 Linux 或 Mac 的系统上安装,请在终端中运行以下命令: ``` sudo bash -c 'curl -L https://github.com/dolthub/dolt/releases/latest/download/install.sh | bash' ``` 这将下载最新的 `dolt` 版本,并放到 `/usr/local/bin/` 中,该路径很可能已在你的 `$PATH` 中。 安装脚本需要 sudo 权限,以便将 `dolt` 放到 `/usr/local/bin` 中。如果你没有 root 权限,或不愿以 root 权限运行脚本,可以从[最新版本](https://github.com/dolthub/dolt/releases),)下载适用于你平台的 dolt 二进制文件,解压后,将二进制文件放到 `$PATH` 上的某个位置。 ### Linux #### Arch Linux Dolt 已收录在 Arch Linux 的官方软件仓库中。 ``` pacman -S dolt ``` ### Mac #### Homebrew Dolt 已上架 Homebrew,每个版本发布时都会更新。 ``` brew install dolt ``` #### MacPorts 在 macOS 上,也可以通过 [MacPorts](https://www.macports.org):) 的[社区维护 port](https://ports.macports.org/port/dolt/)) 安装 Dolt。 ```sh sudo port install dolt ``` ### Windows 在 [releases](https://github.com/dolthub/dolt/releases)) 中下载最新的 Microsoft Installer(`.msi` 文件)并运行。 有关在 Windows 上运行的信息,请参见[此处](https://dolthub.com/docs/introduction/installation/windows).。 #### Chocolatey 你可以使用 [Chocolatey](https://chocolatey.org/):) 安装 `dolt`。 ```sh choco install dolt ``` #### Docker Dolt 提供以下官方 Docker 镜像: * [`dolthub/dolt`](https://hub.docker.com/r/dolthub/dolt)):将 Dolt 作为 CLI 工具运行。 * [`dolthub/dolt-sql-server`](https://hub.docker.com/r/dolthub/dolt-sql-server)):以服务器模式运行 Dolt。 ## 从源码构建 请确保已安装 Go,且 `go` 在你的 path 中。Dolt 依赖 [cgo](https://pkg.go.dev/cmd/cgo),),因此你还需要可用的 C 编译器和工具链。 克隆此仓库并进入 `go` 目录。然后运行: ``` go install ./cmd/dolt ``` 输出将位于 `$GOPATH/bin`,默认值为 `~/go/bin`。要测试你的构建,请尝试: ``` ~/go/bin/dolt version ``` # 配置 在终端中运行 `dolt`,验证安装是否成功。 ``` $ dolt Valid commands for dolt are [...] ``` 使用你的用户名和邮箱配置 `dolt`,创建提交时需要这些信息。命令用法与 git 完全相同。 ``` $ dolt config --global --add user.email YOU@DOMAIN.COM $ dolt config --global --add user.name "YOUR NAME" ``` # 入门 ## 导航到你想存放数据的目录 Dolt 需要一个位置来存储你的数据库。我将把数据库放在 `~/dolt`。 ```bash % cd ~ % mkdir dolt % cd dolt ``` 你创建的任何数据库都会存储在此目录中。因此,在本示例中,运行 `create database getting_started` 后,将在此处创建一个名为 `getting_started` 的目录。进入 `~/dolt/getting_started` 后,即可使用 Dolt 命令行访问该数据库。 注意:在本示例中,`getting_started` 目录将在你在 [Create a schema section](#create-a-schema) 的 SQL shell 中运行 `create database getting_started;` 后创建。目前只需创建目录并进入即可,不要执行其他操作。 ## 启动兼容 MySQL 的数据库服务器 Dolt 内置了一个与 MySQL 兼容的数据库服务器。要启动它,请使用命令 `dolt sql-server`。运行该命令后,服务器会在 3306 端口启动。 ```bash dolt sql-server Starting server with Config HP="localhost:3306"|T="28800000"|R="false"|L="info" ``` 此时终端会停在那里不动。这表示服务器正在运行。任何错误都会打印在这个终端中。让它保持运行,并打开一个新的终端。 ## 使用 MySQL 客户端连接(最高支持 8.4 版本) 在新的终端中,我们将使用客户端连接到正在运行的数据库服务器。Dolt 也自带了一个与 MySQL 兼容的客户端。 ```bash % dolt -u root -p "" sql # Welcome to the Dolt MySQL client. # Statements must be terminated with ';'. # "exit" or "quit" (or Ctrl-D) to exit. mysql> ``` 在运行 `dolt sql-server` 的另一个终端中,你会看到以下日志行。 ``` 2022-06-06T13:14:32-07:00 INFO [conn 1] NewConnection {DisableClientMultiStatements=false} ``` 你已经连接成功! 趁这个机会,我们先安装一份 MySQL,以便使用该客户端进行连接。请前往 [MySQL Getting Started](https://dev.mysql.com/doc/mysql-getting-started/en/) 文档,在你的机器上安装 MySQL。我在 Mac 上使用 [Homebrew](https://brew.sh/) 安装 MySQL:`brew install mysql@8.4`。或者,你也可以通过运行 `brew install mysql-client@8.4` 仅安装客户端组件。 注意:请确保安装的是 MySQL 8.4 版本。MySQL 8.4 是当前长期支持(Long Term Support,LTS)版本,也就是说它是 MySQL 稳定且受支持的版本。MySQL 9.0 也可获得,但属于“创新”(innovation)版本,意味着它包含更多最新变更和功能,但可能不如 LTS 版本稳定。9.0 版本更改了认证支持,默认情况下无法连接到 Dolt SQL 服务器。你可以通过运行 `brew install mysql@8.4` 用 Homebrew 安装 MySQL 8.4。如果你确实想使用 MySQL 9.0,请阅读[我们关于如何为 `caching_sha2_password` 认证配置 Dolt 的文章](https://www.dolthub.com/blog/2024-12-11-mysql9-and-caching-sha2-auth-support/). MySQL 附带一个名为 `mysqld` 的 MySQL 服务器和一个名为 `mysql` 的 MySQL 客户端。你只需关注客户端。按照 MySQL 文档中的说明操作后,请确保你的路径上有 `mysql` 客户端: ```bash % mysql --version mysql Ver 8.0.29 for macos12.2 on x86_64 (Homebrew) ``` 现在,要将 `mysql` 客户端连接到 Dolt,你需要通过传入主机和端口,强制 MySQL 客户端走 TCP 接口。默认使用的是 socket 接口,Dolt 也支持该接口,但仅在 `localhost` 上可用。因此,更好的做法是演示 TCP 接口。MySQL 客户端还要求你指定用户,此处为 `root`。 ```bash % mysql --host 127.0.0.1 --port 3306 -uroot Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.7.9-Vitess Copyright (c) 2000, 2022, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> ``` 同样,为了确认客户端确实已连接,你应该在 `dolt sql-server` 终端中看到以下内容 ``` 2022-06-06T13:26:55-07:00 INFO [conn 2] NewConnection {DisableClientMultiStatements=false} ``` 如你所见,Dolt 支持任何与 MySQL 兼容的客户端。Dolt 自带客户端,但你可以使用任何 MySQL 客户端,例如 MySQL 自带的那个。 ## 创建 schema 现在我们终于可以做些有意思的事了。我会留在 `mysql` 客户端中,执行以下 SQL 语句来创建一个名为 `getting_started` 的数据库。`getting_started` 数据库将包含三张表:`employees`、`teams` 和 `employees_teams`。 ``` mysql> create database getting_started; Query OK, 1 row affected (0.04 sec) mysql> use getting_started; Database changed mysql> create table employees ( id int, last_name varchar(255), first_name varchar(255), primary key(id)); Query OK, 0 rows affected (0.01 sec) mysql> create table teams ( id int, team_name varchar(255), primary key(id)); Query OK, 0 rows affected (0.00 sec) mysql> create table employees_teams( team_id int, employee_id int, primary key(team_id, employee_id), foreign key (team_id) references teams(id), foreign key (employee_id) references employees(id)); Query OK, 0 rows affected (0.01 sec) mysql> show tables; +---------------------------+ | Tables_in_getting_started | +---------------------------+ | employees | | employees_teams | | teams | +---------------------------+ 3 rows in set (0.00 sec) ``` Dolt 支持外键、二级索引、触发器、检查约束和存储过程。它是一个功能丰富的现代 SQL 数据库。 ## 创建 Dolt commit 是时候使用你的第一个 Dolt 功能了。我们将创建一个 Dolt [commit](https://dolthub.com/docs/concepts/dolt/commits). Dolt commit 允许你进行时间旅行并查看血缘关系。每当你想恢复到这一时间点或与之进行比较时,就创建一个 Dolt commit。 Dolt 通过类似 Git 的界面暴露版本控制功能。在命令行中,Dolt 命令与对应的 Git 命令一一映射,只是目标对象从文件变成了表。在 SQL 中,Dolt 将版本控制的读操作暴露为[系统表](https://dolthub.com/docs/sql-reference/version-control/dolt-system-tables),将版本控制的写操作暴露为[存储过程](https://dolthub.com/docs/sql-reference/version-control/dolt-sql-procedures). 系统表和存储过程的命名遵循 `dolt_` 模式。因此,CLI 中的 `dolt add` 会变成存储过程 `dolt_add`。传递选项也遵循命令行模型。例如,要指定要添加的表,请将表名作为选项传给 `dolt_add` 存储过程。对于命名参数,例如向 `dolt_commit` 命令发送消息,请按顺序使用两个参数,如 `('-m', 'This is a message')`。如果你熟悉 Git,这些版本控制存储过程和系统表应该会感觉很熟悉。 那么,我们像这样添加并提交新 schema。 ``` mysql> call dolt_add('teams', 'employees', 'employees_teams'); +--------+ | status | +--------+ | 0 | +--------+ 1 row in set (0.03 sec) mysql> call dolt_commit('-m', 'Created initial schema'); +----------------------------------+ | hash | +----------------------------------+ | ne182jemgrlm8jnjmoubfqsstlfi1s98 | +----------------------------------+ 1 row in set (0.02 sec) mysql> select * from dolt_log; +----------------------------------+-----------+-----------------+-------------------------+----------------------------+ | commit_hash | committer | email | date | message | +----------------------------------+-----------+-----------------+-------------------------+----------------------------+ | ne182jemgrlm8jnjmoubfqsstlfi1s98 | Tim Sehn | tim@dolthub.com | 2022-06-07 16:35:49.277 | Created initial schema | | vluuhvd0bn59598utedt77ed9q5okbcb | Tim Sehn | tim@dolthub.com | 2022-06-07 16:33:59.531 | Initialize data repository | +----------------------------------+-----------+-----------------+-------------------------+----------------------------+ 2 rows in set (0.01 sec) ``` 就是这样。你的 schema 已创建,并且有一个 Dolt commit 在跟踪这次创建,可以在 `dolt_log` 系统表中看到。 请注意,Dolt commit 不同于标准 SQL 事务 `COMMIT`。在本例中,我启用了 [`AUTOCOMMIT`](https://dev.mysql.com/doc/refman/5.6/en/innodb-autocommit-commit-rollback.html) 运行数据库,因此每条 SQL 语句都会自动生成事务 `COMMIT`。如果你希望系统为每个事务生成 Dolt commit,请使用系统变量 [`@@dolt_transaction_commit`](https://dolthub.com/docs/sql-reference/version-control/dolt-sysvars#dolt_transaction_commit). ## 插入一些数据 现在,我要向数据库中填入 DoltHub 的几位员工。然后,我会把这些员工分配到两个团队:工程(engineering)和销售(sales)。在初创公司里,CEO 身兼数职,所以他会同时被分配到多个团队。 ``` mysql> insert into employees values (0, 'Sehn', 'Tim'), (1, 'Hendriks', 'Brian'), (2, 'Son','Aaron'), (3, 'Fitzgerald', 'Brian'); Query OK, 4 rows affected (0.01 sec) mysql> select * from employees where first_name='Brian'; +------+------------+------------+ | id | last_name | first_name | +------+------------+------------+ | 1 | Hendriks | Brian | | 3 | Fitzgerald | Brian | +------+------------+------------+ 2 rows in set (0.00 sec) mysql> insert into teams values (0, 'Engineering'), (1, 'Sales'); Query OK, 2 rows affected (0.00 sec) mysql> insert into employees_teams values (0,0), (1,0), (2,0), (0,1), (3,1); ERROR 1452 (HY000): cannot add or update a child row - Foreign key violation on fk: `rv9ek7ft`, table: `employees_teams`, referenced table: `teams`, key: `[2]` ``` 哎呀,我违反了约束。看来我创建表时把 teams 放在 employees 前面了。插入时应该始终明确指定列,而不要依赖自然顺序。活该!Dolt 具备现代 SQL 关系型数据库的全部能力,可确保数据完整性。 ``` mysql> insert into employees_teams(employee_id, team_id) values (0,0), (1,0), (2,0), (0,1), (3,1); Query OK, 5 rows affected (0.01 sec) mysql> select first_name, last_name, team_name from employees join employees_teams on (employees.id=employees_teams.employee_id) join teams on (teams.id=employees_teams.team_id) where team_name='Engineering'; +------------+-----------+-------------+ | first_name | last_name | team_name | +------------+-----------+-------------+ | Tim | Sehn | Engineering | | Brian | Hendriks | Engineering | | Aaron | Son | Engineering | +------------+-----------+-------------+ 3 rows in set (0.00 sec) ``` 看起来一切都已正确插入。我能够用那个三表 `JOIN` 列出工程团队的成员。Dolt 最多支持十二表 `JOIN`s。再说一次,Dolt 是现代 SQL 关系型数据库,并配有 Git 风格的版本控制。 ## 查看 diff 现在,如果你想在提交之前查看工作区里有哪些变更,可以使用 `dolt_status` 和 `dolt_diff_` 系统表。 ``` mysql> select * from dolt_status; +-----------------+--------+----------+ | table_name | staged | status | +-----------------+--------+----------+ | teams | 0 | modified | | employees | 0 | modified | | employees_teams | 0 | modified | +-----------------+--------+----------+ 3 rows in set (0.01 sec) mysql> select * from dolt_diff_employees; +--------------+---------------+-------+-----------+----------------+----------------+-----------------+---------+----------------------------------+-------------------------+-----------+ | to_last_name | to_first_name | to_id | to_commit | to_commit_date | from_last_name | from_first_name | from_id | from_commit | from_commit_date | diff_type | +--------------+---------------+-------+-----------+----------------+----------------+-----------------+---------+----------------------------------+-------------------------+-----------+ | Sehn | Tim | 0 | WORKING | NULL | NULL | NULL | NULL | ne182jemgrlm8jnjmoubfqsstlfi1s98 | 2022-06-07 16:35:49.277 | added | | Hendriks | Brian | 1 | WORKING | NULL | NULL | NULL | NULL | ne182jemgrlm8jnjmoubfqsstlfi1s98 | 2022-06-07 16:35:49.277 | added | | Son | Aaron | 2 | WORKING | NULL | NULL | NULL | NULL | ne182jemgrlm8jnjmoubfqsstlfi1s98 | 2022-06-07 16:35:49.277 | added | | Fitzgerald | Brian | 3 | WORKING | NULL | NULL | NULL | NULL | ne182jemgrlm8jnjmoubfqsstlfi1s98 | 2022-06-07 16:35:49.277 | added | +--------------+---------------+-------+-----------+----------------+----------------+-----------------+---------+----------------------------------+-------------------------+-----------+ 4 rows in set (0.00 sec) ``` 从 diff 可以看出,我已向 `employees` 表添加了正确的值。这些值之前是 `NULL`,现在已填充完成。 最后再来一次 Dolt 提交,这次用 `-am` 添加所有受影响的表。 ``` mysql> call dolt_commit('-am', 'Populated tables with data'); +----------------------------------+ | hash | +----------------------------------+ | 13qfqa5rojq18j84d1n2htjkm6fletg4 | +----------------------------------+ 1 row in set (0.02 sec) ``` 你可以用 `dolt_log` 检查日志,并用不带作用域的 `dolt_diff` 查看每次提交中哪些表发生了变更。不带作用域的 `dolt_diff` 会告诉你该次提交中该表的 schema、data 或二者是否发生了变化。 ``` mysql> select * from dolt_log; +----------------------------------+-----------+-----------------+-------------------------+----------------------------+ | commit_hash | committer | email | date | message | +----------------------------------+-----------+-----------------+-------------------------+----------------------------+ | 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn | tim@dolthub.com | 2022-06-07 16:39:32.066 | Populated tables with data | | ne182jemgrlm8jnjmoubfqsstlfi1s98 | Tim Sehn | tim@dolthub.com | 2022-06-07 16:35:49.277 | Created initial schema | | vluuhvd0bn59598utedt77ed9q5okbcb | Tim Sehn | tim@dolthub.com | 2022-06-07 16:33:59.531 | Initialize data repository | +----------------------------------+-----------+-----------------+-------------------------+----------------------------+ 3 rows in set (0.00 sec) mysql> select * from dolt_diff; +----------------------------------+-----------------+-----------+-----------------+-------------------------+----------------------------+-------------+---------------+ | commit_hash | table_name | committer | email | date | message | data_change | schema_change | +----------------------------------+-----------------+-----------+-----------------+-------------------------+----------------------------+-------------+---------------+ | 13qfqa5rojq18j84d1n2htjkm6fletg4 | teams | Tim Sehn | tim@dolthub.com | 2022-06-07 16:39:32.066 | Populated tables with data | 1 | 0 | | 13qfqa5rojq18j84d1n2htjkm6fletg4 | employees | Tim Sehn | tim@dolthub.com | 2022-06-07 16:39:32.066 | Populated tables with data | 1 | 0 | | 13qfqa5rojq18j84d1n2htjkm6fletg4 | employees_teams | Tim Sehn | tim@dolthub.com | 2022-06-07 16:39:32.066 | Populated tables with data | 1 | 0 | | ne182jemgrlm8jnjmoubfqsstlfi1s98 | employees | Tim Sehn | tim@dolthub.com | 2022-06-07 16:35:49.277 | Created initial schema | 0 | 1 | | ne182jemgrlm8jnjmoubfqsstlfi1s98 | employees_teams | Tim Sehn | tim@dolthub.com | 2022-06-07 16:35:49.277 | Created initial schema | 0 | 1 | | ne182jemgrlm8jnjmoubfqsstlfi1s98 | teams | Tim Sehn | tim@dolthub.com | 2022-06-07 16:35:49.277 | Created initial schema | 0 | 1 | +----------------------------------+-----------------+-----------+-----------------+-------------------------+----------------------------+-------------+---------------+ 6 rows in set (0.00 sec) ``` ## 糟了!我犯了个错误。 Dolt 支持通过 `call dolt_reset()` 撤销变更。假设我不小心删了一张表。 ``` mysql> drop table employees_teams; Query OK, 0 rows affected (0.01 sec) mysql> show tables; +---------------------------+ | Tables_in_getting_started | +---------------------------+ | employees | | teams | +---------------------------+ 2 rows in set (0.00 sec) ``` 在传统数据库中,这可能会带来灾难性后果。在 Dolt 中,你只需一条命令就能恢复表。 ``` mysql> call dolt_reset('--hard'); +--------+ | status | +--------+ | 0 | +--------+ 1 row in set (0.01 sec) mysql> show tables; +---------------------------+ | Tables_in_getting_started | +---------------------------+ | employees | | employees_teams | | teams | +---------------------------+ 3 rows in set (0.01 sec) ``` Dolt 让数据库运维更少出错。你随时可以回滚进行中的更改,或回溯到已知的良好状态。你还可以使用 [`dolt_revert()`](https://dolthub.com/docs/sql-reference/version-control/dolt-sql-procedures#dolt_revert). 撤销特定提交。即使你意外在错误的数据库上运行了 `drop database`,Dolt 也允许你通过调用 [`dolt_undrop()` stored procedure](https://dolthub.com/docs/sql-reference/version-control/dolt-sql-procedures#dolt_undrop). 来撤销该操作。 ## 在 SQL Workbench 中查看数据 讨厌命令行?让我们使用 [Tableplus](https://tableplus.com/) 进行一些修改。Tableplus 是一款免费的 SQL Workbench。请按照其官网的安装说明进行操作。 现在,要连接数据库,你必须选择 MySQL 作为连接类型。然后为连接输入一个名称,将 `getting_started` 作为数据库,将 `root` 作为用户。 ![Tableplus Connection](./images/getting-started-tp-connect.png) 点击连接后,你将看到一个熟悉的数据库 workbench GUI。 ![Tableplus](./images/getting-started-tp.png) ## 在分支上进行更改 要在分支上进行更改,我使用 `dolt_checkout()` 存储过程。使用 `-b` 选项会创建分支,就像在 Git 中一样。 Tableplus 让我可以在 SQL 选项卡中输入多行 SQL 脚本。我输入了以下 SQL,用于检出分支、更新、插入、删除,最后 Dolt commit 我的更改。 ```SQL call dolt_checkout('-b','modifications'); update employees SET first_name='Timothy' where first_name='Tim'; insert INTO employees (id, first_name, last_name) values (4,'Daylon', 'Wilkins'); insert into employees_teams(team_id, employee_id) values (0,4); delete from employees_teams where employee_id=0 and team_id=1; call dolt_commit('-am', 'Modifications on a branch'); ``` 以下是 Tableplus 中的结果。 ![New Updates](./images/getting-started-new-updates.png) 回到终端后,我看不到在 Tableplus 中所做的表修改,因为这些更改发生在与我当前会话中检出的分支不同的分支上。 ``` mysql> select * from dolt_branches; +---------------+----------------------------------+------------------+------------------------+-------------------------+----------------------------+ | name | hash | latest_committer | latest_committer_email | latest_commit_date | latest_commit_message | +---------------+----------------------------------+------------------+------------------------+-------------------------+----------------------------+ | main | 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn | tim@dolthub.com | 2022-06-07 16:39:32.066 | Populated tables with data | | modifications | uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim Sehn | tim@dolthub.com | 2022-06-07 16:41:49.847 | Modifications on a branch | +---------------+----------------------------------+------------------+------------------------+-------------------------+----------------------------+ 2 rows in set (0.00 sec) mysql> select active_branch(); +-----------------+ | active_branch() | +-----------------+ | main | +-----------------+ 1 row in set (0.00 sec) mysql> select * from employees; +------+------------+------------+ | id | last_name | first_name | +------+------------+------------+ | 0 | Sehn | Tim | | 1 | Hendriks | Brian | | 2 | Son | Aaron | | 3 | Fitzgerald | Brian | +------+------------+------------+ 4 rows in set (0.00 sec) ``` 无论当前检出的是哪个分支,我都可以使用 SQL `as of` 语法查询该分支。 ``` mysql> select * from employees as of 'modifications'; +------+------------+------------+ | id | last_name | first_name | +------+------------+------------+ | 0 | Sehn | Timothy | | 1 | Hendriks | Brian | | 2 | Son | Aaron | | 3 | Fitzgerald | Brian | | 4 | Wilkins | Daylon | +------+------------+------------+ 5 rows in set (0.01 sec) ``` 如果我想查看两个分支之间的 diff,可以使用 `dolt_diff()` 表函数。它接受两个分支和表名作为参数。 ``` mysql> select * from dolt_diff('main', 'modifications', 'employees'); +--------------+---------------+-------+---------------+-------------------------+----------------+-----------------+---------+-------------+-------------------------+-----------+ | to_last_name | to_first_name | to_id | to_commit | to_commit_date | from_last_name | from_first_name | from_id | from_commit | from_commit_date | diff_type | +--------------+---------------+-------+---------------+-------------------------+----------------+-----------------+---------+-------------+-------------------------+-----------+ | Sehn | Timothy | 0 | modifications | 2022-06-07 16:41:49.847 | Sehn | Tim | 0 | main | 2022-06-07 16:39:32.066 | modified | | Wilkins | Daylon | 4 | modifications | 2022-06-07 16:41:49.847 | NULL | NULL | NULL | main | 2022-06-07 16:39:32.066 | added | +--------------+---------------+-------+---------------+-------------------------+----------------+-----------------+---------+-------------+-------------------------+-----------+ 2 rows in set (0.00 sec) ``` 如你所见,借助 Dolt,你可以在 SQL 数据库中获得 Git 风格分支和 diff 的全部能力。 ## 在另一个分支上进行 schema 更改 我也可以在分支上进行 schema 更改,以便对新 schema 进行隔离测试。我将在新分支上添加 `start_date` 列并填充数据。 ``` mysql> call dolt_checkout('-b', 'schema_changes'); +--------+ | status | +--------+ | 0 | +--------+ 1 row in set (0.01 sec) mysql> alter table employees add column start_date date; Query OK, 0 rows affected (0.02 sec) mysql> update employees set start_date='2018-09-08'; Query OK, 4 rows affected (0.01 sec) Rows matched: 4 Changed: 4 Warnings: 0 mysql> update employees set start_date='2021-04-19' where last_name='Fitzgerald'; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from employees; +------+------------+------------+------------+ | id | last_name | first_name | start_date | +------+------------+------------+------------+ | 0 | Sehn | Tim | 2018-09-08 | | 1 | Hendriks | Brian | 2018-09-08 | | 2 | Son | Aaron | 2018-09-08 | | 3 | Fitzgerald | Brian | 2021-04-19 | +------+------------+------------+------------+ 4 rows in set (0.00 sec) mysql> call dolt_commit('-am', 'Added start_date column to employees'); +----------------------------------+ | hash | +----------------------------------+ | pg3nfi0j1dpc5pf1rfgckpmlteaufdrt | +----------------------------------+ 1 row in set (0.01 sec) ``` 在分支上更改 schema 为你提供了一种对新 schema 更改进行隔离集成测试的新方法。 ## 全部合并 假设在 `schema_changes` 分支上对新 schema 的测试,以及在 `modifications` 分支上的数据测试都已顺利完成。是时候将所有编辑合并到 `main` 上了。这通过 `dolt_merge` 存储过程完成。 ``` mysql> call dolt_checkout('main'); +--------+ | status | +--------+ | 0 | +--------+ 1 row in set (0.01 sec) mysql> select * from dolt_status; Empty set (0.00 sec) mysql> call dolt_merge('schema_changes'); +--------------+ | no_conflicts | +--------------+ | 1 | +--------------+ 1 row in set (0.01 sec) mysql> select * from employees; +------+------------+------------+------------+ | id | last_name | first_name | start_date | +------+------------+------------+------------+ | 0 | Sehn | Tim | 2018-09-08 | | 1 | Hendriks | Brian | 2018-09-08 | | 2 | Son | Aaron | 2018-09-08 | | 3 | Fitzgerald | Brian | 2021-04-19 | +------+------------+------------+------------+ 4 rows in set (0.00 sec) ``` Schema 变更成功。我们现在有了开始日期(start dates)。接下来进行数据变更。 ``` mysql> call dolt_merge('modifications'); +--------------+ | no_conflicts | +--------------+ | 1 | +--------------+ 1 row in set (0.02 sec) mysql> select * from employees; +------+------------+------------+------------+ | id | last_name | first_name | start_date | +------+------------+------------+------------+ | 0 | Sehn | Timothy | 2018-09-08 | | 1 | Hendriks | Brian | 2018-09-08 | | 2 | Son | Aaron | 2018-09-08 | | 3 | Fitzgerald | Brian | 2021-04-19 | | 4 | Wilkins | Daylon | NULL | +------+------------+------------+------------+ 5 rows in set (0.00 sec) ``` 数据变更也成功了。如你所见,我现在是 "Timothy" 而不是 "Tim",Daylon 已被添加,我们所有人都有开始日期,除了 Daylon——他是在另一个分支上添加的。 ``` mysql> select first_name, last_name, team_name from employees join employees_teams on (employees.id=employees_teams.employee_id) join teams on (teams.id=employees_teams.team_id) where team_name='Sales'; +------------+------------+-----------+ | first_name | last_name | team_name | +------------+------------+-----------+ | Brian | Fitzgerald | Sales | +------------+------------+-----------+ 1 row in set (0.01 sec) ``` 我也离开了 Sales Team。Engineering 才是王道。 我必须提交所有更改,因为上次合并不是快进(fast-forward)合并。 ``` mysql> call dolt_commit('-m', 'Merged all branches'); +----------------------------------+ | hash | +----------------------------------+ | vn9b0qcematsj2f6ka0hfoflhr5s6p0b | +----------------------------------+ 1 row in set (0.01 sec) mysql> select * from dolt_log; +----------------------------------+-----------+-----------------+-------------------------+--------------------------------------+ | commit_hash | committer | email | date | message | +----------------------------------+-----------+-----------------+-------------------------+--------------------------------------+ | vn9b0qcematsj2f6ka0hfoflhr5s6p0b | Tim Sehn | tim@dolthub.com | 2022-06-07 17:10:02.07 | Merged all branches | | pg3nfi0j1dpc5pf1rfgckpmlteaufdrt | Tim Sehn | tim@dolthub.com | 2022-06-07 16:44:37.513 | Added start_date column to employees | | uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim Sehn | tim@dolthub.com | 2022-06-07 16:41:49.847 | Modifications on a branch | | 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn | tim@dolthub.com | 2022-06-07 16:39:32.066 | Populated tables with data | | ne182jemgrlm8jnjmoubfqsstlfi1s98 | Tim Sehn | tim@dolthub.com | 2022-06-07 16:35:49.277 | Created initial schema | | vluuhvd0bn59598utedt77ed9q5okbcb | Tim Sehn | tim@dolthub.com | 2022-06-07 16:33:59.531 | Initialize data repository | +----------------------------------+-----------+-----------------+-------------------------+--------------------------------------+ 6 rows in set (0.00 sec) ``` 现在,我们有了一个数据库,其中所有 schema 和数据变更都已合并,可以投入使用。 ## 审计单元格血缘(Cell Lineage) 是哪个 commit 更改了我的名字?使用 Dolt,你可以追踪数据库中每个单元格的血缘。让我们使用 `dolt_history_` 和 `dolt_diff_` 来探索 Dolt 中的血缘功能。 `dolt_history_` 会显示该行在每一个 commit 时的状态。 ``` mysql> select * from dolt_history_employees where id=0 order by commit_date; +------+-----------+------------+------------+----------------------------------+-----------+-------------------------+ | id | last_name | first_name | start_date | commit_hash | committer | commit_date | +------+-----------+------------+------------+----------------------------------+-----------+-------------------------+ | 0 | Sehn | Tim | NULL | 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn | 2022-06-07 16:39:32.066 | | 0 | Sehn | Timothy | NULL | uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim Sehn | 2022-06-07 16:41:49.847 | | 0 | Sehn | Tim | 2018-09-08 | pg3nfi0j1dpc5pf1rfgckpmlteaufdrt | Tim Sehn | 2022-06-07 16:44:37.513 | | 0 | Sehn | Timothy | 2018-09-08 | vn9b0qcematsj2f6ka0hfoflhr5s6p0b | Tim Sehn | 2022-06-07 17:10:02.07 | +------+-----------+------------+------------+----------------------------------+-----------+-------------------------+ 4 rows in set (0.00 sec) ``` `dolt_diff_` 允许你将历史记录筛选为仅显示目标单元格发生变更的 commit。在这种情况下,我关心的是更改我名字的 commit。注意,有两个 commit 更改了我的名字,其中一个是原始变更,另一个是 merge commit。 ``` mysql> select to_commit,from_first_name,to_first_name from dolt_diff_employees where (from_id=0 or to_id=0) and (from_first_name <> to_first_name or from_first_name is NULL) order by to_commit_date; +----------------------------------+-----------------+---------------+ | to_commit | from_first_name | to_first_name | +----------------------------------+-----------------+---------------+ | 13qfqa5rojq18j84d1n2htjkm6fletg4 | NULL | Tim | | uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim | Timothy | | vn9b0qcematsj2f6ka0hfoflhr5s6p0b | Tim | Timothy | +----------------------------------+-----------------+---------------+ 3 rows in set (0.01 sec) ``` Dolt 提供了强大的数据审计能力,可精确到单个单元格。数据库中的每个单元格随时间是如何、为何以及何时发生变更的? # 延伸阅读 既然你已经对 Dolt 有了初步了解,请前往 [我们的文档](https://dolthub.com/docs/introduction/what-is-dolt)。你也可以在 [我们的博客](https://www.dolthub.com/blog/). 中了解我们一直在做什么。 # 安全策略 [Dolt 当前的安全策略](https://github.com/dolthub/dolt/blob/main/SECURITY.md) 维护在本仓库中。请按照其中的披露说明操作。请勿在本仓库的公开 GitHub Issues 中初次报告安全问题。 # 致谢与许可 Dolt 大量依赖来自 [Noms](https://github.com/attic-labs/noms) 项目的开源代码和理念。我们非常感谢 Noms 团队免费提供这些代码, 没有它们,我们无法如此快速地构建 Dolt。 Dolt 采用 Apache License, Version 2.0 许可。详见 [LICENSE](https://github.com/dolthub/dolt/blob/master/LICENSE)。