アーカイブ「2018年06月」

MariaDBでMultisource Replicationをやるときは、

  • GTIDベース
  • 通常ベース(ファイル/ポジション)

によって、制約が異なる。

 

GTIDベースでは、

レプリケーション元のgtid_domain_idが異なっていなければならない。

通常ベースでは、

レプリケーション元のgtid_domain_idが同じでも良い。

 

つまり、GTIDベースでは、以下のようなケースにおいては、

db01とdb02のgtid_domain_idは異る必要がある。

+++++          +++++
db01           db02
+++++          +++++
|              |
|              |
++++++++++++++++++++
multisource
++++++++++++++++++++

 

しかし、通常ベースでは、gtid_domain_idが同じでもよい。

これは、gtid_domain_idを指定できないAWSのRDS環境のおいても、

Multisource Replicationが使えることを意味している。

つまり、db01とdb02がRDSで、multisourceがEC2という位置付けになる。

※RDS上にmultisourceは組めません。

 

さらに、MariaDBの嬉しい機能として、

コネクションごとに、replicate_do_dbやらreplicate_igonore_dbが指定できる。

たとえば、db01へのコネクション名を「con-db01」、db02へのコネクション名を「con-db02」とすると、

以下のような設定をmultisource側のmy.cnfに記載できる。

con-db01.replicate_do_db=hoge01
con-db02.replicate_do_db=hoge02

この設定の意味するところは、「con-db01」ではhoge01データベースをレプリケーションの対象とする、

「con-db02」ではhoge02データベースをレプリケーションの対象とする、ということである。

 

このような機能を使うことで、

分割されたDBからデータをかき集め、

様々な集計/分析を行うことが容易となる。

さらに、MariaDB10.2からはwindow関数も導入されているため、

Multisource Replicationによる恩恵もおおきくなるだろう。

※MariaDB10.2と10.3では使えるwindow関数が異なるので注意。

 

なお、GTIDを使う場合、以下のように、2つのGTIDを指定する。

gtid_domain_idが10はdb01、20はdb02を指している。

> stop all slaves;
> SET GLOBAL gtid_slave_pos='10-11-10,20-21-10';
> CHANGE MASTER 'con-db01' TO  MASTER_HOST='XXX', MASTER_USER='rpl', MASTER_PASSWORD='rplpassword', master_use_gtid=slave_pos;
> CHANGE MASTER 'con-db02' TO  MASTER_HOST='YYY', MASTER_USER='rpl', MASTER_PASSWORD='rplpassword', master_use_gtid=slave_pos;
> start all slaves;

 

以上

投稿日時:2018年06月14日 23:51   カテゴリー:mariadb   [コメントがあればどうぞ]

表題のとおり、MariaDB10.3とOracleをconnectエンジンで繋いでみた。

つなぎ方は、odbcかjdbcを使うことで実現できる。

Oracleのクライアント設定とかも必要なので、

ここでは詳細な設定について割愛。

 

なお、Oracleとの互換性を最大限たかめるため、

SQL_MODE=ORACLE

という、MariaDB10.3で導入されたモードを設定している。

 

おおよそのデータについては、問題なくconnectエンジン経由で扱えるのだが、

最大の難関は日付けである。

Oracleはtimestamp型を拡張しているため、

MariaDB(MySQL)のtimestamp型とカバー範囲が異なる。

そのため、以下の条件のいずれかの場合において、

connectで持ってきた時に「0000-00-00 00:00:00」という日時になってしまう。

  • Oracleのtimestamp型データがMySQLのtimestamp型の範囲外のとき
  • Oracleのtimestamp型データがNULLのとき

前者はその通りの話ではあるが、後者のパターンも有り得るのがやっかいである。

しかも、条件句で指定した時は、NULLと認識するくせに、結果セットが変るのである。

これはconnectで自動作成させるテーブル定義上仕方ないことなのであるが。。

 

その他、BLOB、CLOBなどのバイナリ型が、

connect上はvarcharになるので、このあたりも場合によっては、注意が必要。

 

以上

投稿日時:2018年06月14日 23:16   カテゴリー:mariadb   [コメントがあればどうぞ]

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の正しさ」を保証することが可能でした。

 

以上

投稿日時:2018年06月14日 22:46   カテゴリー:mysql   [コメントがあればどうぞ]