GA

2014/01/24

groonga-index-dumpで遊んでみる

これがやりたくてtweets.csvをMroongaに食わせていた

$ time /usr/ruby/2.0.0/bin/groonga-index-dump /usr/mysql/5.6.15/data/mroonga.mrn

real    0m33.430s
user    0m29.649s
sys     0m2.924s

$ ll
合計 16
drwxr-xr-x 2 root     root     4096  7月  3 19:14 2013 hsperfdata_root
drwxr-xr-x 2 yoku0825 yoku0825 4096 11月  6 11:49 2013 hsperfdata_ttanaka
drwxrwxr-x 3 yoku0825 yoku0825 4096  1月 24 12:04 2014 index-dump
drwx------ 2 yoku0825 tmux    4096  1月 10 15:19 2014 tmux-3012

--output-directoryで指定しない場合はカレントディレクトリの下にindex-dumpディレクトリを掘る。

$ cd index-dump/

$ ll
合計 2012
drwxrwxr-x 2 yoku0825 yoku0825 2056192  1月 24 12:04 2014 tweets-text.index

$ cd tweets-text.index/

$ ll | wc
  47997  479962 3723665

index-dumpの下に<テーブル名>-<インデックス名>.indexディレクトリが作られるぽい。
ls -l叩くと泣きたくなるくらいにファイルの数が多い。

$ ll | head
合計 201992
-rw-rw-r-- 1 yoku0825 yoku0825    222  1月 24 12:04 2014 %21%21%21%21%21%21%21%21%21%21%21%21%21%21.dump
-rw-rw-r-- 1 yoku0825 yoku0825    218  1月 24 12:04 2014 %21%21%21%21%21%21%21%E3%80%8D.dump
-rw-rw-r-- 1 yoku0825 yoku0825    256  1月 24 12:04 2014 %21%21%21%21%21%21%21.dump
-rw-rw-r-- 1 yoku0825 yoku0825    337  1月 24 12:04 2014 %21%21%21%21%21%21.dump
-rw-rw-r-- 1 yoku0825 yoku0825    216  1月 24 12:04 2014 %21%21%21%21%21%E3%80%8D.dump
-rw-rw-r-- 1 yoku0825 yoku0825    417  1月 24 12:04 2014 %21%21%21%21%21.dump
-rw-rw-r-- 1 yoku0825 yoku0825    218  1月 24 12:04 2014 %21%21%21%21%E3%80%8D%E3%80%8C.dump
-rw-rw-r-- 1 yoku0825 yoku0825    417  1月 24 12:04 2014 %21%21%21%21.dump
-rw-rw-r-- 1 yoku0825 yoku0825    212  1月 24 12:04 2014 %21%21%21%28.dump

なんかざっと見ただけで、1つのトークンに対して1つの<トークン>.dumpファイルが出来上がっている予感。

$ cat %21%21%21%21%21%21%21%21%21%21%21%21%21%21.dump
index: tweets-text.index        term: <!!!!!!!!!!!!!!>  domain: tweets-text     range: tweets   have_section: false     have_weight: false    have_position: true
  weight        position        term_frequency  record
  0     74      1       tweets[398641294714499072].text

$ cat %E3%81%84%E3%81%BC.dump
index: tweets-text.index        term: <いぼ>    domain: tweets-text     range: tweets   have_section: false     have_weight: false    have_position: true
  weight        position        term_frequency  record
  0     40      1       tweets[198244626002481152].text

やりたいことは myisam_ftdump 的なことなので、この.dumpファイルをテキトーにパースしてやらないといけないっぽい。

取りあえず、投げやりなPerlワンライナーで。

$ cat `ls | head -1000` | perl -nle 'if (/\sterm:\s<(.+)>\s/) {printf("%d\t%s\n", $count, $term); $term= $1; $count= 0;} elsif (/\s([0-9]+)\s+tweets\[[0-9]+\]\.text$/) {$count+= $1;}' | sort -nr | head
12305   、
11013   。
9295    @
7042    /
4599    :
3583    。。
3479    #
2577    ://
2561    (
2243    「

cat *でやろうとしたらなんか怒られた(´・ω・`)

$ cat * | perl -nle 'if (/\sterm:\s<(.+)>\s/) {printf("%d\t%s\n", $count, $term); $
term= $1; $count= 0;} elsif (/\s([0-9]+)\s+tweets\[[0-9]+\]\.text$/) {$count+= $1;}' | sort -nr | head
cat: オプションが違います -- '%'
詳しくは `cat --help' を実行して下さい.

これで索引の中の無駄なトークンをあぶりだしてメンテしてやるのがゴールのつもり。


【2014/01/24 13:46】
catがダメなのは"-"で始まるファイルっぽい。

$ for f in *; do cat $f > /dev/null || (echo $f; break); done
cat: オプションが違います -- '%'
詳しくは `cat --help' を実行して下さい.
-%23.dump
cat: オプションが違います -- '%'
詳しくは `cat --help' を実行して下さい.
-%25%27.dump
cat: オプションが違います -- '%'
詳しくは `cat --help' を実行して下さい.
-%26.dump
..

cat ./*にしたら食えた。

$ cat ./* | perl -nle 'if (/\sterm:\s<(.+)>\s/) {printf("%d\t%s\n", $count, $term); $term= $1; $count= 0;} elsif (/\s([0-9]+)\s+tweets\[[0-9]+\]\.text$/) {$count+= $1;}' | sort -nr | head
12305   、
11013   。
10217   _
9295    @
7042    /
6456    って
4599    :
4514    mysql
4147    ない
3801    5

うん、mysql多いなオイ。

全文検索のテスト用にtweets.csvを食わせるSQL

毎回手打ちするのが面倒なのでメモ。

mysql> CREATE TABLE tweets (tweet_id bigint unsigned primary key, timestamp timestamp NOT NULL, text text NOT NULL, FULLTEXT KEY(text)) Engine= mroonga;
Query OK, 0 rows affected (0.05 sec)

mysql> LOAD DATA INFILE '/tmp/tweets.csv' INTO TABLE tweets FIELDS TERMINATED BY ',' ENCLOSED BY '"' IGNORE 1 ROWS (tweet_id, @dummy, @dummy, @timestamp, @dummy, text, @dummy) SET timestamp= DATE_ADD(@timestamp, INTERVAL 9 HOUR);
Query OK, 14410 rows affected, 28821 warnings (0.35 sec)
Records: 14410  Deleted: 0  Skipped: 0  Warnings: 28821

CSVのtext以降の部分をTRUNCATEしたってワーニングがごちゃっと出る。
timestampは"2013-12-17 03:06:59 +0000"(=UTC)の形で入っていて、SET TIME_ZONEで頑張ってみたけど上手く行かなかったのでSETで無理矢理9時間足してみた。

2014/01/23

Galera Arbitratorというもの(garbd)

Galera Cluster(俺が実際に色々やってるのはPercona XtraDB Cluster)はスプリットブレイン対策としてQuorum方式を採用している。クラスターを構成するノードの *過半数* とコミュニケーションが取れていない場合、自身がネットワークから切り離されているとみなして *全ての操作を* 拒否するようになる。Galera Clusterはそもそも全てのノードのデータが「仮想完全同期」されているという前提でマルチマスターのトポロジーを提供しているため、コミュニケーションパスが途切れて同期できていないかもしれない状態は、マルチマスターを提供するための下地が崩れるからこうなっている。

mysql> use test
ERROR 1047 (08S01): Unknown command

mysql> SELECT * FROM d1.t1;
ERROR 1047 (08S01): Unknown command

出力はこんな感じで、何をしてもError: 1047のUnknown commandが返ってくるようになる。流石にmysqlコマンドラインクライアントだけで完結するコマンド(helpとかcharsetとかteeとか)は実行できるけど、サーバー側から情報を引っ張って何かするコマンド(statusとuseくらい?)は実行できなくなる。

で、コミュニケーションパスが生きている必要があるノードはクラスターを構成するノードの *過半数* なので、2台構成にしてしまうと1台お亡くなりになった時に 残った1台> 2* 50% が成り立たないため、生き残った1台はこの状態に突入する。これを避けるために、Galera Clusterは最低3台での構成を推奨 している。

SET GLOBAL wsrep_provider_options= 'pc.ignore_sb= ON'; という手もあるけれど(名前の通り、スプリットブレイン状態になっててもコマンドを拒否しなくなる)、本当にネットワークがおかしくなった時に何が起こるかわからない(2つのmysqldそれぞれに矛盾する更新がかかったら、とか、更新が伝達されずにレコードを読んじゃったら、とか)ので、あまりやりたくない。かといって物理サーバー3台…うーん、微妙。

そんなわたしに贈る、Galera Arbitrator。プロセス名はgarbd。

$ ll /usr/local/mysql5534_pxc/bin/garbd
-rwxr-xr-x 1 root root 18015250 12月  2 21:20 /usr/local/mysql5534_pxc/bin/garbd

Percona XtraDB Cluster 5.5.34の.tar.gzのバイナリーを解凍した版にはbinの下に入ってた。ソースからコンパイルした人にはいない。どこから手に入れるのかもよく判らないけど、ソースからコンパイルした人、libの下にlibgalera_smm.soもなくて別途codershipから取ってきて入れないといけないから、そこから入れるのかな。PXCなら.tar.gz版がオールインワンで扱いやすいと思う余談。MariaDB Galera Clusterは(入ってるのか入ってないのか)知らない。

$ /usr/local/mysql5534_pxc/bin/garbd --help

Usage: /usr/local/mysql5534_pxc/bin/garbd [options] [group address]

Configuration:
  -d [ --daemon ]       Become daemon
  -a [ --address ] arg  Group address
  -g [ --group ] arg    Group name
  --sst arg             SST request string
  --donor arg           SST donor name
  -o [ --options ] arg  GCS/GCOMM option list
  -l [ --log ] arg      Log file
  -c [ --cfg ] arg      Configuration file


Other options:
  -v [ --version ]      Print version
  -h [ --help ]         Show help message

FATAL: Exit

ざっくりと、必要最低限っぽいオプションは-a(PXCのwsrep_cluster_addressに相当)と-g(PXCのwsrep_cluster_nameに相当)かしら。

$ /usr/local/mysql5534_pxc/bin/garbd -a "gcomm://xxx.xxx.xxx.xxx:13333" -g "cluster_name" -o "gmcast.listen_addr= tcp://0.0.0.0:13334"
2014-01-23 12:13:20.944  INFO: Read config:
        daemon:  0
        address: gcomm://xxx.xxx.xxx.xxx:13333
        group:   cluster_name
        sst:     trivial
        donor:
        options: gmcast.listen_addr= tcp://0.0.0.0:13334; gcs.fc_limit=9999999; gcs.fc_factor=1.0; gcs.fc_master_slave=yes
        cfg:
        log:

2014-01-23 12:13:20.952  INFO: protonet asio version 0
2014-01-23 12:13:20.953  INFO: backend: asio
2014-01-23 12:13:20.967  INFO: GMCast version 0
2014-01-23 12:13:20.972  INFO: (50019916-83dc-11e3-a310-bfb42459a728, 'tcp://0.0.0.0:13334') listening at tcp://0.0.0.0:13334
2014-01-23 12:13:20.972  INFO: (50019916-83dc-11e3-a310-bfb42459a728, 'tcp://0.0.0.0:13334') multicast: , ttl: 1
2014-01-23 12:13:20.992  INFO: EVS version 0
2014-01-23 12:13:21.000  INFO: PC version 0
2014-01-23 12:13:21.000  INFO: gcomm: connecting to group 'cluster_name', peer 'xxx.xxx.xxx.xxx:13333'
2014-01-23 12:13:21.007  INFO: (50019916-83dc-11e3-a310-bfb42459a728, 'tcp://0.0.0.0:13334') turning message relay requesting on, nonlive peers: tcp://xxx.xxx.xxx.xxx:13332
2014-01-23 12:13:21.489  INFO: (50019916-83dc-11e3-a310-bfb42459a728, 'tcp://0.0.0.0:13334') turning message relay requesting off
2014-01-23 12:13:21.505  INFO: declaring 1663d468-79c2-11e3-a5e5-2f016f2db075 stable
2014-01-23 12:13:21.505  INFO: declaring bc9b8196-83d6-11e3-b4d0-1a4766eec11e stable
2014-01-23 12:13:21.506  INFO: Node 1663d468-79c2-11e3-a5e5-2f016f2db075 state prim
2014-01-23 12:13:21.506  INFO: view(view_id(PRIM,1663d468-79c2-11e3-a5e5-2f016f2db075,43) memb {
        1663d468-79c2-11e3-a5e5-2f016f2db075,
        50019916-83dc-11e3-a310-bfb42459a728,
        bc9b8196-83d6-11e3-b4d0-1a4766eec11e,
} joined {
} left {
} partitioned {
})
2014-01-23 12:13:22.005  INFO: gcomm: connected
2014-01-23 12:13:22.005  INFO: Changing maximum packet size to 64500, resulting msg size: 32636
2014-01-23 12:13:22.005  INFO: Shifting CLOSED -> OPEN (TO: 0)
2014-01-23 12:13:22.005  INFO: Opened channel 'cluster_name'
2014-01-23 12:13:22.006  INFO: New COMPONENT: primary = yes, bootstrap = no, my_idx = 1, memb_num = 3
2014-01-23 12:13:22.006  INFO: STATE EXCHANGE: Waiting for state UUID.
2014-01-23 12:13:22.006  INFO: STATE EXCHANGE: sent state msg: 5055781a-83dc-11e3-b9e1-e2687a7bb5a6
2014-01-23 12:13:22.006  INFO: STATE EXCHANGE: got state msg: 5055781a-83dc-11e3-b9e1-e2687a7bb5a6 from 0 (xxxx_3333)
2014-01-23 12:13:22.006  INFO: STATE EXCHANGE: got state msg: 5055781a-83dc-11e3-b9e1-e2687a7bb5a6 from 2 (xxxx_3332)
2014-01-23 12:13:22.007  INFO: STATE EXCHANGE: got state msg: 5055781a-83dc-11e3-b9e1-e2687a7bb5a6 from 1 (garb)
2014-01-23 12:13:22.007  INFO: Quorum results:
        version    = 2,
        component  = PRIMARY,
        conf_id    = 33,
        members    = 2/3 (joined/total),
        act_id     = 29266,
        last_appl. = -1,
        protocols  = 0/4/2 (gcs/repl/appl),
        group UUID = 64863b36-62f7-11e3-bef2-a746941be182
2014-01-23 12:13:22.007  INFO: Flow-control interval: [9999999, 9999999]
2014-01-23 12:13:22.007  INFO: Shifting OPEN -> PRIMARY (TO: 29266)
2014-01-23 12:13:22.007  INFO: Sending state transfer request: 'trivial', size: 7
2014-01-23 12:13:22.007  INFO: Node 1 (garb) requested state transfer from '*any*'. Selected 0 (xxxx_3333)(SYNCED) as donor.
2014-01-23 12:13:22.007  INFO: Shifting PRIMARY -> JOINER (TO: 29266)
2014-01-23 12:13:22.008  INFO: 0 (xxxx_3333): State transfer to 1 (garb) complete.
2014-01-23 12:13:22.008  INFO: 1 (garb): State transfer from 0 (xxxx_3333) complete.
2014-01-23 12:13:22.008  INFO: Shifting JOINER -> JOINED (TO: 29266)
2014-01-23 12:13:22.008  INFO: Member 0 (xxxx_3333) synced with group.
2014-01-23 12:13:22.008  INFO: Member 1 (garb) synced with group.
2014-01-23 12:13:22.008  INFO: Shifting JOINED -> SYNCED (TO: 29266)

"gmcast.listen_addr= tcp://0.0.0.0:13334"は、このノード既にPXCが3インスタンスいるのでポートがカブらないように調整しているだけで、フツーにPXCのmysqldを起動させた時と同じように、コミュニケーションパスを使って自分のステータスをSYNCEDまで持って行ってる。SST(=フル同期)はしない。

他のノードからSHOW GLOBAL STATUS LIKE 'wsrep_cluster_size'で見ると、確かに増えている。これでmysqldが3つなくても、1台落ちただけなら過半数を満たせる数が確保できるという算段。APサーバーの先頭か何かにgarbdだけ入れておけばね。


……MHA-Managerみたい。。

2014/01/22

Percona XtraDB Cluster設定中に気付いたwsrep_certify_nonPK

Primary Keyが無いテーブル + Galera Clusterで悲惨な目に なんていうことが昔ありました。

PXC(wsrepの要求なので、Gelara Cluster for MySQL, MariaDB Galera Cluster も同じ)はbinlog_format= ROW が必須パラメーターになっているのでPrimary Keyが無いと悲惨な目に遭うんですが、これを強制的に禁止するオプション(wsrep_certify_nonPK)を発見。

mysql> SELECT @@wsrep_certify_nonPK;
+-----------------------+
| @@wsrep_certify_nonPK |
+-----------------------+
|                     1 |
+-----------------------+
1 row in set (0.00 sec)

デフォルトはON。

mysql> CREATE TABLE d1.t1 ( num INT, val varchar(32) ) Engine= InnoDB;
Query OK, 0 rows affected (0.02 sec)

mysql> INSERT INTO d1.t1 VALUES (1, 'one');
Query OK, 1 row affected (0.00 sec)

mysql> UPDATE d1.t1 SET val= 'eins' WHERE num= 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT * FROM d1.t1;
+------+------+
| num  | val  |
+------+------+
|    1 | eins |
+------+------+
1 row in set (0.00 sec)

mysql> DELETE FROM d1.t1 WHERE num= 1;
Query OK, 1 row affected (0.00 sec)

Primary Keyが無くてもINSERTもUPDATEもDELETEもできる。フツーの動作。

mysql> SET GLOBAL wsrep_certify_nonPK= OFF;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@wsrep_certify_nonPK;
+-----------------------+
| @@wsrep_certify_nonPK |
+-----------------------+
|                     0 |
+-----------------------+
1 row in set (0.00 sec)

これをOFFる。と、想像通り、

mysql> INSERT INTO d1.t1 VALUES (1, 'one');
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

容赦なく蹴られるように。
Error 1213のDeadlock found.. が表示されるのは、全ノード間でデータの同期を保証する為の2相コミットっぽい仕組み(実際には2相コミットじゃない)で失敗したから(これをwsrepではCertificationと呼んでいる)で、Local Certification Failure(XA Prepare的なのに失敗)はError 1213 Deadlock found..で返される仕様になっているから。

なお飽くまで"Local" Certification Failureなので、他の(wsrep_certify_nonPK= ONな)ノードでINSERTするとINSERTできる。よって、設定する時は全てに設定しておくこと。


ところでこの動作、MariaDBには標準で無かったっけ? とか思ったけど違った。RBRの時にPkeyが無いテーブルへの更新は拒否する、じゃなくて、RBRの時でPkeyが無いテーブルへの更新でも最適化してスレーブに適用してくれる、という風情らしい。

Row-based replication with no primary key

Perconaがオリジナルだっていうのも知らなかった。

2014/01/20

mysqlコマンドラインクライアントでuseの代わりにcdを使う

何を言っているのか略という感じな気もするタイトルですね。。
話の流れとしては、


とか馬鹿なこと言ってたら
とツッコミが入ったので、やってみました。
最初はuseはステートメントだと思っていたので、SQLパーサーをいじって USEステートメント をCDステートメントに変えてやろうと思っていたんですが、"SQLデリミターを省略しても実行される", "mysqlコマンドラインクライアント上でhelp叩くと出てくる"からmysqlコマンドラインクライアント上のコマンドだよ、とツッコミをもらい、そっちをいじくってみることに。

mysql-5.6.15/client/mysql.ccのこのあたりですね。

 322 static COMMANDS commands[] = {
..
 357   { "use",    'u', com_use,    1,
 358     "Use another database. Takes database name as argument." },
..

mysqlコマンドラインクライアント上のuseコマンドを叩くとcom_use関数が呼ばれて、com_use関数の中でmysql_select_db(&mysql, ..)を叩いてcurrent_dbを変更しています。
com_use関数以降は同じで構わないので、ここだけちゃちゃっと変えてコンパイル。


$ client/mysql -uroot -S /usr/mysql/5.6.15/data/mysql.sock
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 5.6.15-log Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

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> help

For information about MySQL products and services, visit:
   http://www.mysql.com/
For developer information, including the MySQL Reference Manual, visit:
   http://dev.mysql.com/
To buy MySQL Enterprise support, training, or other products, visit:
   https://shop.mysql.com/

List of all MySQL commands:
Note that all text commands must be first on line and end with ';'
?         (\?) Synonym for `help'.
clear     (\c) Clear the current input statement.
connect   (\r) Reconnect to the server. Optional arguments are db and host.
delimiter (\d) Set statement delimiter.
edit      (\e) Edit command with $EDITOR.
ego       (\G) Send command to mysql server, display result vertically.
exit      (\q) Exit mysql. Same as quit.
go        (\g) Send command to mysql server.
help      (\h) Display this help.
nopager   (\n) Disable pager, print to stdout.
notee     (\t) Don't write into outfile.
pager     (\P) Set PAGER [to_pager]. Print the query results via PAGER.
print     (\p) Print current command.
prompt    (\R) Change your mysql prompt.
quit      (\q) Quit mysql.
rehash    (\#) Rebuild completion hash.
source    (\.) Execute an SQL script file. Takes a file name as an argument.
status    (\s) Get status information from the server.
system    (\!) Execute a system shell command.
tee       (\T) Set outfile [to_outfile]. Append everything into given outfile.
cd        (\u) Use another database. Takes database name as argument.
charset   (\C) Switch to another charset. Might be needed for processing binlog with multi-byte charsets.
warnings  (\W) Show warnings after every statement.
nowarning (\w) Don't show warnings after every statement.

For server side help, type 'help contents'

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| d1                 |
| mysql              |
| performance_schema |
| test               |
+--------------------+
5 rows in set (0.00 sec)

mysql> SELECT database();
+------------+
| database() |
+------------+
| NULL       |
+------------+
1 row in set (0.02 sec)

mysql> cd d1
Database changed

mysql> SELECT database();
+------------+
| database() |
+------------+
| d1         |
+------------+
1 row in set (0.00 sec)

mysql> use mysql
    -> ;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT database();
+------------+
| database() |
+------------+
| mysql      |
+------------+
1 row in set (0.00 sec)

helpの結果がuseコマンドからcdコマンドになり、useを叩くと末尾にセミコロンを求められる。で、セミコロンつけて送信するとMySQLのパーサーがUSEステートメントとして解釈するから"Query OK, .."の応答メッセージ。

ううむ、意外と面白いぞこれ。

2014/01/15

Percona XtraDB Cluster設計の迷いどころ(現在進行形)=> 解決

今、とあるサービスに Percona XtraDB Cluster を突っ込むことを画策しているんですが、今まさに迷っている真っ最中なのでメモしておきます。誰か何か思いついたら教えてください。

Percona XtraDB Cluster(以下PXC)というか Galera Replication の仕組みというかコンセプトというか自体が、「マルチマスターなMySQL *の* クラスター」なわけで、PXCを使えばこれは簡単に実現できます。

が。

PXCでマルチマスターすると、バイナリーログの扱いがちょっと問題になってきます。
wsrep providerが提供するPXC内の同期はGalera Cacheと呼ばれる専用のバイナリーログ(からヘッダーを取り除いたもの)に格納され、同期されます。Galera Cacheのファイルは(どういう仕組みなのか調べてないけれど)原則として一定サイズで(必要に応じて拡張され、必要なくなったら元に戻る)、これだけ見てるとInnoDBログファイルみたいにシーケンシャルに書いて、ファイルの末端に言ったら先頭に戻っている気がしなくもないです(調べてないです)

これは別にどうでも良いんですが、Galera Cacheを使って同期されたデータは log-slave-updates で拾えず、つまりバイナリーログは *更新SQLを受け取ったmysqldのみ* が保存します。
この前提かつマルチマスターにすると、

バ イ ナ リ ー ロ グ が 複 数 台 に 分 散 さ れ 、 ポ イ ン ト イ ン タ イ ム リ カ バ リ ー が 出 来 な い

ことになるんじゃないでしょうか。ってか、今のところなってます。
分散するところまでは良いです。バックアップ用と割り切れば、 MariaDB 10.0のマルチソースレプリケーション とか、 MySQL 5.7のLabs版 でlog-slave-updatesもアリな気はします。MySQLには 由緒正しいN:1レプリケーション もありますが、今回はデータをごにょごにょしたいのではなくバイナリーログの保全が目的になるのでちょっとこの方式は取れなそうです。

いや、MariaDB 10.0もMySQL 5.7も *シリアライズを保証できない* 時点で完全にアウトなんですけどね :(

バイナリーログを一箇所に集めたところで、PITRの為に流しなおす範囲のバイナリーログを全てデコードして、時間順に並べ変えて…としても、バイナリーログは秒までしか時間を保存しないので、その間に同じレコードが2度更新されたりすると、どっちが最終状態として正しいのか判らなくなってPITRの一貫性が崩れる。

かといってGalera Cacheは上手く吸い上げてやるにはファイルの機構がバイナリーログとは違いそうだし、なんともかんともはや。。

codershipのフォーラムでも未対応ってことになってた(URLわかんなくなった。。)んですが、一応 *将来ね!* って雰囲気ではありました。

どうしようかなー。。


【2014/01/15 14:59】
今現在はこんなことを考えてます。。





【2014/07/09 17:36】
バージョンアップで出来るようになってた! これで(この迷いどころは)なくなったぞ!
Percona XtraDB Clusterでいつの間にかPITRできるようになってた