Git for Data「Dolt」というDBの話
ここ最近、何やらデータベースの相談をされることが何やら多くなってきたmasamikiです。
今、とあるプロダクトの開発をしようと、要件まとめたり設計したりたりしてるのですが、この仕組みをやるためには…version管理いるなぁ…gitが欲しいなぁ……となってます。
そして、調べてみたところ、2年も前のものですがこんな記事を見つけました。
「DoltとDoltHubが我々の結論だ」とおっしゃってます。
Doltとは
Doltは、Gitリポジトリと同じように、フォーク、クローン作成、ブランチ、マージ、プッシュ、プルできる最初で唯一のSQLデータベースです。(← by Google翻訳)
おぉ、まさしく、そのままんま、これだ。
他にも、GitRows とかも使えそうかな…と思ってみていたものの、どうやら今の要件にあうのあはDoltっぽそう。
上記事だと、他にもdata.world(Microsoft Dataverseみたいなもんですかね…?)やDVC(機械学習プロジェクト用のオープンソース
バージョン管理システム)とかまだ触ったことないものも記載されていたので、ちょっとどっかで試してみたいなと思いながら、今回はDoltを触ってみます。
Qiitaでも2020年に記事にしてる方がいらしゃいますね → RDBのデータの構成管理ができるDoltとは
インストール
ここ以降の話は、大体↓に書いてあるので、原文みてやりたいかたはどうぞ。
macはhomebrewで入れられるので、コマンドはこれだけ。(mac前提で進めます)
brew install dolt
サーバーの起動
以下のコマンドで実行します。
dolt sql-server
あ、3306がすでに別のサービスに使われてたので、ポートを3307に変えてやり直し。
dolt sql-server -P 3307
接続
DoltはMySQLのclientでアクセスできるらしく(portもdefaultで3306)、接続するならこんな感じ。
mysql --host 127.0.0.1 --port 3306 -uroot
そのまま使えるのいいですね。
データベース作成
データベースの作成もMySQLと同じ。
create database test;
表示も同じ。(client一緒ですからね。)
+--------------------+
| Database |
+--------------------+
| information_schema |
| test |
+--------------------+
2 rows in set (0.00 sec)
テーブル作成
もう、MySQLと同じなので書く必要もなさそうですが、こんな感じ。
use test;
create table employees (
last_name varchar(255),
first_name varchar(255),
title varchar(255),
date_started date,
primary key(last_name, first_name)
);
+-----------+
| Table |
+-----------+
| employees |
+-----------+
1 row in set (0.00 sec)
コミット
そう、ここからが知りたいところです。
gitライクな操作、どうなるのか?
まずはcommitから。
commitには、dolt_commit
というのを使います。コマンドはこんな感じ。
select dolt_commit('-a', '-m', 'Created employees table');
-aオプションはすべての変更済みのテーブル、-mオプションはメッセージと、これもgitと同じですね。
そして、select
を実行の為に使うみたいです。
+----------------------------------------------------+
| dolt_commit('-a', '-m', 'Created employees table') |
+----------------------------------------------------+
| h99ip189o6nuad7f8c8951654o9eu86a |
+----------------------------------------------------+
1 row in set (0.01 sec)
データの挿入とコミットだとこんな感じ。
insert into employees values ('Sehn', 'Tim', 'CEO', '2018-08-06');
select dolt_commit('-a', '-m', 'Inserted Tim Sehn, CEO');
+-----------+------------+-------+--------------+
| last_name | first_name | title | date_started |
+-----------+------------+-------+--------------+
| Sehn | Tim | CEO | 2018-08-06 |
+-----------+------------+-------+--------------+
1 row in set (0.00 sec)
+---------------------------------------------------+
| dolt_commit('-a', '-m', 'Inserted Tim Sehn, CEO') |
+---------------------------------------------------+
| j6iv0hmmho21oe1uh3pnit6i3vf5p3jc |
+---------------------------------------------------+
1 row in set (0.01 sec)
ブランチきる
ブランチをきるというか、checkoutは dolt_checkout
でやるようです。
これも、-bオプションで新しいブランチを作成しながらcheckoutするみたいです。
(switchじゃないのか)
select dolt_checkout('-b', 'hoge');
すると以下のようなレスポンスが返ってきます。
+-----------------------------+
| dolt_checkout('-b', 'hoge') |
+-----------------------------+
| 0 |
+-----------------------------+
1 row in set (0.01 sec)
インサートして
insert into employees values ('Son', 'Aaron', 'Founder', '2018-08-06');
+-----------+------------+---------+--------------+
| last_name | first_name | title | date_started |
+-----------+------------+---------+--------------+
| Sehn | Tim | CEO | 2018-08-06 |
| Son | Aaron | Founder | 2018-08-06 |
+-----------+------------+---------+--------------+
2 rows in set (0.01 sec)
commit。
select dolt_commit('-a', '-m', 'Inserted Adron, Founder');
+----------------------------------------------------+
| dolt_commit('-a', '-m', 'Inserted Adron, Founder') |
+----------------------------------------------------+
| r9rrob8t4jct6kucsmpdt238emnqjcec |
+----------------------------------------------------+
1 row in set (0.03 sec)
mainに戻って
select dolt_checkout('main');
見る。
+-----------+------------+-------+--------------+
| last_name | first_name | title | date_started |
+-----------+------------+-------+--------------+
| Sehn | Tim | CEO | 2018-08-06 |
+-----------+------------+-------+--------------+
1 row in set (0.01 sec)
おぉ、消えてる。
マージ
hogeブランチに入れたデータをマージします。
select dolt_merge('hoge');
+--------------------+
| dolt_merge('hoge') |
+--------------------+
| 1 |
+--------------------+
1 row in set, 1 warning (0.01 sec)
見る。
+-----------+------------+---------+--------------+
| last_name | first_name | title | date_started |
+-----------+------------+---------+--------------+
| Sehn | Tim | CEO | 2018-08-06 |
| Son | Aaron | Founder | 2018-08-06 |
+-----------+------------+---------+--------------+
2 rows in set (0.00 sec)
おぉ、マージされた。
log
commitのログをみるのもgitと同じくlogを使うみたいです。
ただ、これまのクエリと異なり、テーブルを参照するようなクエリになるもよう。
select * from dolt_log;
+----------------------------------+---------------------+----------------------+-------------------------+----------------------------+
| commit_hash | committer | email | date | message |
+----------------------------------+---------------------+----------------------+-------------------------+----------------------------+
| r9rrob8t4jct6kucsmpdt238emnqjcec | Dolt System Account | doltuser@dolthub.com | 2022-01-01 05:09:34.799 | Inserted Adron, Founder |
| j6iv0hmmho21oe1uh3pnit6i3vf5p3jc | Dolt System Account | doltuser@dolthub.com | 2022-01-01 04:09:56.746 | Inserted Tim Sehn, CEO |
| h99ip189o6nuad7f8c8951654o9eu86a | Dolt System Account | doltuser@dolthub.com | 2022-01-01 04:08:04.903 | Created employees table |
| 1gehtq3ftbd7a350s5prern2orm1gepq | Dolt System Account | doltuser@dolthub.com | 2022-01-01 04:01:24.411 | Initialize data repository |
+----------------------------------+---------------------+----------------------+-------------------------+----------------------------+
Dolt SQL Functions一覧
このdolt_hogeのSQLは、Dolt SQL Functionsという名前でのようですが、こんなものが用意されているみたいです。
gitと同じなので、Fucntionの内容はイメージしやすいですね。
dolt_commit()
dolt_add()
dolt_checkout()
dolt_merge()
dolt_reset()
dolt_push()
dolt_fetch()
dolt_pull()
dolt_merge_base()
hash_of()
Dolt テーブル一覧
logもそうでしたが、Doltは以下のようなテーブルを持っていて、システムとしての情報が保管されています。
dolt_branches
dolt_commit_diff
dolt_diff
dolt_docs
dolt_history
dolt_commit_ancestors
dolt_log
dolt_status
dolt_conflicts
dolt_conflicts_$tablename
dolt_constraint_violations
dolt_constraint_violations_$tablename
dolt_procedures
dolt_schemas
dolt_remotes
なのでブランチを見たいときは、
select * from dolt_branches;
+------+----------------------------------+---------------------+------------------------+-------------------------+-------------------------+
| name | hash | latest_committer | latest_committer_email | latest_commit_date | latest_commit_message |
+------+----------------------------------+---------------------+------------------------+-------------------------+-------------------------+
| hoge | r9rrob8t4jct6kucsmpdt238emnqjcec | Dolt System Account | doltuser@dolthub.com | 2022-01-01 05:09:34.799 | Inserted Adron, Founder |
| main | r9rrob8t4jct6kucsmpdt238emnqjcec | Dolt System Account | doltuser@dolthub.com | 2022-01-01 05:09:34.799 | Inserted Adron, Founder |
+------+----------------------------------+---------------------+------------------------+-------------------------+-------------------------+
コンフリクト
気になる大きな問題は、conflictどうするのかですよね。
Hogeの追加
select dolt_checkout('-b', 'hogehoge');
UPDATE employees SET title='CTO';
select dolt_commit('-a', '-m', 'Hoge');
select dolt_checkout('main');
Fugaの追加
select dolt_checkout('-b', 'fugafuga');
UPDATE employees SET title='CFO';
select dolt_commit('-a', '-m', 'Fuga');
select dolt_checkout('main');
Hogeのマージ
select dolt_merge('hogehoge');
select dolt_commit('-a', '-m', 'Merge');
+------------------------+
| dolt_merge('hogehoge') |
+------------------------+
| 1 |
+------------------------+
1 row in set (0.02 sec)
Fugaのマージ
select dolt_merge('fugafuga');
ERROR 1105 (HY000): merge has unresolved conflicts. please use the dolt_conflicts table to resolve
エラーが返るようです。
select dolt_commit('-a', '-m', 'Merge');
ERROR 1105 (HY000): error: the table(s) employees in conflict
commitもできないようにちゃんとなってます。
では、tableを拝見。
select * from dolt_conflicts;
ERROR 1105 (HY000): merge has unresolved conflicts. please use the dolt_conflicts table to resolve
あれ?
これでコンフリクトの数みたいなのが出るはずなのですが、でない……
詰んだ…
とりあえず、conflictしたものは、dolt_conflicts_{{テーブル名}}に入るそうで、現時点のブランチを正とするならば、コンフリクトを削除すればいいとのこと。
DELETE FROM dolt_conflicts_employees;
select dolt_commit('-a', '-m', 'Merge');
+----------------------------------+
| dolt_commit('-a', '-m', 'Merge') |
+----------------------------------+
| 199augn48g1bkjftog7rfn67oa5s7pe4 |
+----------------------------------+
1 row in set (0.03 sec)
解消できたようです。
ちょっと、コンフリクトの内容見れないのは困りましたね…
コンフリクトの解消方法もコードと違って難しそう。
プログラム言語
mysql clientに対応してることもあり(コンフリクトのレスポンスをうまくえられませんでしたが…)、大抵の言語は、mysqlのライブラリをそのまま用いればいいようです。
例えば、Goであれば、go-sql-driver/mysql packageが使えます。
CLI
SQLでなくとも、Dolt自体のCLIでいろいろと操作もできるみたいです。
commitであれば、こんな感じ。
dolt commit [options]
まんまgitのコマンドみたいな感じなんで、これもわかりやすいですね。
感想
ちょっと不備を感じましたが(mysqlのclientのバージョンとかのせいな気もしますが)悪くはないなぁと。
データの登録の際にcommitという処理をしておく必要があったり(変更をため込んでも別にいいと思いますが)、コンフリクトの解消が少しやっかいそうというのはあり、ただのDBよりも少し複雑にはなりますが、ブランチというような概念があるといい機能って意外と世の中にはあると思いますし、使いどころが大分ありそうなDBだと思いました。
開発用の環境にも使えそうですよね。大がかりなMigrationをテストしたい時とかも、ブランチ切れるなら遠慮無く流して、またすぐに戻せますしね。コードのブランチにあわせてDBのブランチも変えられるとかはありかなと。(dumpとかスナップショット戻すより楽)
今のプロダクトに採用するかどうかはわからないですが、どっかで利用してみたいなと思います。
Discussion