MySQL8のJSON部分更新を確認してみた。
最初こんなテーブルを作り、データを更新する。
> create database hoge; > use hoge; > create table fuga (id integer not null, body json not null, primary key(id)); > insert into fuga values (1, '{"x":10, "y":20}'); > update fuga set body = json_replace(body, '$.y', 50);
この状態でバイナリログを見ると、以下のようになっている。
### UPDATE `hoge`.`fuga` ### WHERE ### @1=1 ### @2='{"x": 10, "y": 20}' ### SET ### @1=1 ### @2='{"x": 10, "y": 50}'
部分更新じゃなくね?と思ったが、
my.cnfに以下を記載する。
binlog_row_image=minimal binlog_row_value_options=partial_json
再起動完了後、以下のようなSQLを実行する。
> update fuga set body = json_replace(body, '$.y', 12);
この時、バイナリログは、
### UPDATE `hoge`.`fuga` ### WHERE ### @1=1 ### SET ### @2=JSON_REPLACE(@2, '$.y', 12)
となる。
もともと、binlog_row_imageはバイナリログに変更分しか記載しないもので、
5.6から導入されていたが、8ではbinlog_row_value_optionsというパラメータが追加された。
これにより、JSONの部分更新がバイナリログ上でも明示される。
とはいえ、JSONの部分更新を成立させるには、
以下のJSON関数を使う必要がある。
- JSON_SET()
- JSON_REPLACE()
- JSON_REMOVE()
MariaDB10.3でも、binlog_row_value_optionsがないため、
JSONの部分更新はできない。
おまけに、JSONはlongtextのエイリアスのため、
「JSONの正しさ」は保証しない。
JSONを使うなら、virtual columnもあるMSQL8が現時点では良いと思う。
(2018年11月1日追記)
> おまけに、JSONはlongtextのエイリアスのため、
> 「JSONの正しさ」は保証しない。
大変申し訳ありません。
上記は間違っていました。
https://mariadb.com/kb/en/library/json-data-type/
にcheck制約を使うことで、「JSONの正しさ」を保証することが可能でした。
以上
コメントがあればどうぞ