抄訳 Advanced use of Global Transaction Identifiers

引き続きMySQL開発者のSven Sandbergのブログ MySQL Replication Ideas の翻訳版です。原文も確認してください。

Details of Re-execution and Empty Transactions / トランザクションの再実行と空のトランザクション

前回のブログポスト (オリジナル版 http://svenmysql.blogspot.co.uk/2012/10/failover-and-flexible-replication.html / 抄訳版 http://d.hatena.ne.jp/rkajiyama/20130301) では、GTIDがどのように生成され展開されていくかや、新しいレプリケーションプロトコル、フェールオーバーに役立つ要素などについて解説してきました。

今度は、GTIDがどのように機能するのかの詳細を解説します。特に、スレーブのスレッドが同じトランザクションを誤って繰り返し実行しない仕組みを確認します。また、mysqlbinlogでのメカニズムも確認します。トランザクションを空にするコンセプトと、どのように安全にトランザクションを抑制(実行せずにスキップする)かを確認しましょう。

The replication thread / レプリケーションスレッド

前回解説した通り、マスターはGTIDをイベントとして、トランザクションの内容の前にバイナリログに記録します。そして、スレーブのスレッドがGTIDを読むと、スレーブのサーバ変数gtid_nextをそのGTIDで変更します。例えば
スレーブのスレッドが読んだGTIDが4d8b564f-03f4-4975- 856a-0e65c3105328:4711の場合、以下のSQL文を発行します。

SET GTID_NEXT = 4d8b564f-03f4-4975-856a-0e65c3105328:4711;

これによって、スレーブはGTIDを自動生成するのではなく、4d8b564f-03f4-4975-856a-0e65c3105328:4711を利用します。

mysqlbinlog

上記のSQL文は、SUPER権限を持ったどのクライアントからでも実行可能です。
同じ仕組みはmysqlbinlogコマンドでも使われています。mysqlbinlogがGTIDのイベントを読み込むと、自動的にSET GTID_NEXT文を出力します。それによって、mysqlbinlogからの出力を実行するクライアントは、トランザクション内容だけではなくGTIDも同じまま実行が可能となります。

Transactions Must Only Execute Once / トランザクションは一度だけ実行されなければならない

もしGTID_NEXTで指定されたトランザクションが既に実行されていたらどうなるでしょうか?同じトランザクションが再度実行されてはなりません。まずデータの整合性がとれなくなる可能性がありますし、そもそも異なったトランザクションが同じGTIDを持つことはありえません。また、フェールオーバーの際に別のエラーを引き起こしかねません。

そのため、SET GTID_NEXTが実行されると、該当するトランザクションが既に実行されているか、@@GLOBAL.GTID_DONE @@GLOBAL.GTID_EXECUTEDからサーバがチェックします。

  • もしまだ実行されていなければ問題なし。該当するトランザクションを実行する。
  • すでにそのGTIDが@@GLOBAL.GTID_DONE @@GLOBAL.GTID_EXECUTEDに含まれている場合、該当するトランザクションは実行されない。同じトランザクションを再度実行しようとしたことになりため、サーバは無視をし、何も起こらない

Empty Transactions – Making the Slave Skip Transactions / 空のトランザクション - スレーブでトランザクションをスキップする

既に実行されたトランザクションをサーバがスキップするのは、データを破壊してしまうような状況を避けるためだけではありません。GTIDを利用したフィルタリングや、データベース管理者が安全にトランザクションをスキップする、またはレプリケーションを特定の位置から安全にスタートすることを可能とします。(ここでいう安全とは、これらの操作を実行する分かりやすい方法で、次のフェールオーバーなどでデータを誤って破壊するような処理は実装していないことを指します)

下記の例をベースに説明を始めます:
http://3.bp.blogspot.com/-pGvywWPHGp4/UHrkkBFb_EI/AAAAAAAAAEY/jTYy4qhX47k/s1600/1-master-slave.png

AがマスターでBがスレーブです。Aは3つのトランザクションを実行し、Bに全てが転送され適用されています。ここに新たなスレーブCをAに追加するというシナリオです。そしてトランザクションtrx1とtrx2はCで実行したくないとします。この2つのトランザクションをスキップする理由としては、Cは一部のテーブルのみを持つサブセットとする場合でtrx1とtrx2はCが持っていないテーブルに対するトランザクションであるケースや、またはtrx1はミスでtrx2で取り消し処理を行っているケース、またはこれらが非常に大きなトランザクションなので実行したくないケース、さらにはCにとって不要なケースなどが考えられます。

こういった場合には、Cはtrx3からトランザクションを開始したいと考えるでしょう。
http://2.bp.blogspot.com/-1Ks2HilOvFI/UHrklP0RsKI/AAAAAAAAAEc/R9IJ5gf8i2M/s1600/2-master-slave-filter-slave.png

ここでフェールオーバーの際には何が起きるでしょうか?例えばAが停止してしまい、Bを新しいマスターに、CをBのスレーブにします。前回のブログポスト[]での説明の通り、新しいレプリケーションプロトコルでフェールオーバーが可能となっています。CがBに接続すると、CはIDの範囲をBに送り、その範囲に含まれないトランザクションをCに返します。この場合、Cはid3をBに送り、id1のtrx1とid2のtrx2を受け取り、Cでこれらのトランザクションがコミットされます。せっかくスキップしたはずのトランザクションがフェールオーバーによって実行されてしまいます。

この挙動はデータベースを壊してしまいかねない問題だけではありません。(C上でトランザクションが実行される順番が変わっています) エラーメッセージも出さずにデータを壊してしまい、フェールオーバーが発生するというそれだけでもデータベース管理者にとって問題のある状況を悪化させます。さらに、この問題のトランザクションは非常に古い可能性もあります。場合によっては何年も前のトランザクションで、データベース管理者自身もなぜスキップしたのか自体を思い出せずに、デバッグや問題解決を難しい物にしてしまいます。

ここでポイントになるのは、より安全な方法でこれらの状況を回避し、データベース管理者の悪夢を回避することができる点です。

GTID_DONEGTID_EXECUTEDに既に存在するGTIDをGTID_NEXTに設定すると、サーバはそのトランザクションをスキップすることを思い出してください。そこで、GTIDで指定されたトランザクションをスキップするため、まず始めに行うのは同じGTIDを再実行しないように設定することです。
例:

mysql> SET GTID_NEXT = “4d8b564f-03f4-4975-856a-0e65c3105328:4711”;
mysql> COMMIT;

通常、COMMIT文単体では何も起こりません。しかし、GTID_NEXTにGTIDを設定した場合、サーバは空のトランザクションを記録し、バイナリログにはBEGINとCOMMITの間に何も書かれません。
http://4.bp.blogspot.com/-s5iWSPMMfGM/UHrkmlIZzjI/AAAAAAAAAEo/p2iDpiLER-A/s1600/3-empty-transaction.png
これによって、該当のトランザクションは確実にスキップされます。もう同じトランザクションが再度実行されることはありません。

Empty Transactions and Failover / 空のトランザクションとフェールオーバー

先ほどの例にもどって、空のトランザクションを使ってtrx1とtrx2をスキップすると何が起こるかを見ていきましょう。CがスレーブとしてAに接続する前に、GTID id1とid2を空のトランザクションとしてCで実行します。
http://1.bp.blogspot.com/-FpfQExOm-bw/UHrkn-OQeLI/AAAAAAAAAEs/x9Rme2pBSzE/s1600/4-master-slave-filter-slave-with-empty-transaction.png
その後、新しいレプリケーションプロトコルを使ってCをAに接続します。CはGTID_DONE GTID_EXECUTEDをAに送ると、Aはそれ以外の全てをCに送ります。Cは"id1,id2"をAに送り、Aはid3のtrx3を返します。そしてレプリケーションが続きます。

ここまでは我々が必要としているが満たされています。Cはtrx1とtrx2をスキップしレプリケーションを開始しています。ただしid1とid2は存在しています。

では、フェールオーバーが起きるとどうなるでしょうか?Aが停止してしまい、Bを新しいマスターに、CをBのスレーブにします。Cは"id1-id3"をBに送り、Bはそれ以外のトランザクションを返します。trx1とtrx2はCには送られてきません。これらのGTIDは既にCで空のトランザクションで実行されているためです。

この例では、重要なポイントを強調しています。GTIDがサーバの状態も表しています。二つのサーバが同じデータを持っていても、それぞれのバイナリログに含まれるGTIDの範囲が異なる場合は、完全に同じとは見なされません。そして空のトランザクションなどを使うことで問題を起こさないようにできます。

Replication Filters and Empty Transactions / レプリケーションのフィルタリングと空のトランザクション

別のシナリオでは、空のトランザクションレプリケーションのフィルタリングを行う上で重要な役割を担います。このフィルタリングを使って、マスターのデータベースの一部だけをスレーブに持たせる設計が可能です。もしスレーブのサーバを --replicated-ignore-db=mydatabase オプション付きで起動すると、スレーブはマスターから送られてくるバイナリログをチェックし、mydatabaseに関する処理は全てスキップします。

AがマスターでBとCが直接のスレーブだった場合を改めてみていますが、Cがmydatabaseに関する変更点をフィルタリングしているとします。
http://2.bp.blogspot.com/-KZIJODjOpGQ/UHrko13o-OI/AAAAAAAAAE4/kdOvWb2VdOo/s1600/5-replicate-ignore.png
さらにtrx1とtrx2がmydatabaseに対する処理の場合、Cはそれらをスキップします。そしてCでは自動的に空のトランザクションをGTIDのid1とid2として記録します。

もしこの時点でAが停止すると、Bが新しいマスターとなり、CはBのスレーブとなります。このとき空のトランザクションid1とid2がCのGTID_EXECUTEDに記録されています。これによってCはBへの接続時にid1とid2をBに送るため、Bはtrx1とtrx2を再び送信することはありません。

これはパフォーマンスの観点から重要です。特にmydatabaseに対して実行されるトランザクションがmydatabaseそのものと同じぐらい大きい場合など、もしCで空のトランザクションを実行しないと、Bは大量のデータをCに転送する可能性があります。そしてフェールオーバーが既にスキップされたはずの(そして実行されることのない)大量のトランザクションを無駄に受け取ることとなります。

GTID_NEXT is only settable by SUPER / SUPER権限のみがGTID_NEXTを設定可能

繰り返しますがGTID_NEXTを設定するにはSUPER権限が必要です。なぜこうなっているのか。GTID_NEXTが設定されると、マスターで実行された任意のトランザクションを抑制(スキップ)できます。どのユーザがマスターでトランザクションをコミットしても同じです。従って、SUPER権限を持つような特別なユーザのみがGTID_NEXTを設定できるようになっている必要があります。

Summary / まとめ

ここまで見てきたように、スレーブのスレッドはSET GTID_NEXTを実行して、次に実行されるべきトランザクションのGTIDを特定します。mysqlbinlogコマンドでも同様のことができ、またデータベース管理者も必要であれば同じことができます。

既にコミットされたトランザクションは、GTID_NEXTで指定されたものと同じGTIDを持つ場合、スキップされます。

まだ実行されていないトランザクションをスレーブ上でスキップするには、スキップしたいトランザクションのGTIDで空のトランザクションをコミットしておきます。

抄訳 シリーズブログ Failover and Flexible Replication Topologies in MySQL 5.6

MySQL開発者のSven Sandbergのブログ MySQL Replication Ideas からの記事を翻訳してみました。一部は省略してあるのでぜひ原文も確認してください。

追記:なお、原文にあるGTID_DONEはMySQL 5.6.9からGTID_EXECUTEDに変わっています。

他にもいくつかGTID関連のパラメタもMySQL 5.6 GA前に変わっていますのでご注意ください。
MySQL :: MySQL 5.6 Reference Manual :: 17.1.4.5 Global Transaction ID Options and Variables

Global Transaction Identifiers – why, what, and how / GTID - なぜ、なに そして どう使う

MySQL 5.6では新たにGTIDが導入されました。GTIDには数々の用途が想定されますが、我々がGTIDを導入した最大の目的はシームレスなフェールオーバーのためです。これによって、マスターで障害が起きた際には、スレーブの一台が新しいマスターとなります。手動での操作やサービス停止時間を最小限に抑えてこの切り替えを可能とします。

このページはGTIDに関するブログポストの最初です。ここでは、複数の利用例や、いかにフェールオーバーを簡単に行えるかを見ていきます。

以降のブログポストでは、このパワフルな機能のより高度な使い方や、詳細な実装やメカニズムを解説します。これによって、レプリケーション環境のトラブルシューティングや障害解析、フェールオーバー設計、その他の機能の理解が進めばと思います。また外部ツールがGTIDをいかに利用できるかなどを見ていきます。

Use cases / (レプリケーションの)利用例

ツリー型:
http://1.bp.blogspot.com/-RsWiQG1PP9A/UGZHqZvFNvI/AAAAAAAAACg/ZCaNRp0epGI/s1600/1-tree.png
(略)

What GTIDs are not / GTIDでできないこと

GTIDでできないことを明確にしておきましょう。サーバの障害を検知することはできません。外部のユーティリティが必要です。また、障害が発生した後での新しい構成を決定することもできません。クライアントに別のサーバ(生き残ったスレーブなど)を知らせることもできません。これらはそもそも実装されていません。GTIDそのものはこれらの処理を行うためのものではありません。GTIDは、問題のある状態の判断や処理についてはサーバの外部のユーティリティなどで行われることを想定しています。

この後のブログポストでは、これらの判断をどのように行えるかを紹介します。またmysqlfailoverユーティリティで実際にフェールオーバー処理などを実装しています。

Anatomy of a Global Transaction Identifier / GTID詳解

実際のGTIDの利用例を見てみましょう。最初のレプリケーションの利用例を見てみます。
http://2.bp.blogspot.com/-t__m-4W411g/UGZHupvqrwI/AAAAAAAAAC4/zCqtes1sb50/s1600/2-tree-failover.png
サーバAがクラッシュしたため、BかCのどちらかを新しいマスターにしたいとします。

レプリケーションは非同期のため、BとCは全てのトランザクションのコピーや実行が済んでいない可能性があります。片方が他方よりも先行していることも。例えばBの方がCよりも先行している場合、Bを新しいマスター選びます。そして、Bには存在していてCに適用されてないトランザクションからCのレプリケーションを再開します。

では実際にどう動くか。マスターでトランザクションをコミットすると、2つのコンポーネントからなるIDが生成されます。

  • 前半はサーバを一意に表す server_uuid (MySQL 5.6から導入されたグローバル変数 128-bitのランダムな数値が生成され、2つのサーバが同じUUDを持つ可能性は非常に低い)
  • 後半はコミットされたトランザクションの番号。最初のトランザクションは1、次は2というようにコミットごとに1つずつカウントアップ。列のオプションauto_incrementのようなイメージ

前半は、異なったサーバで実行されたトランザクションが異なったGTIDを持つために、後半は同じサーバで実行された複数のトランザクションが異なったGTIDを持つために。

文字列としては、GTIDは“UUID:N”のように表現されます。
例: 22096C54-FE03-4B44-95E7-BD3C4400AF21:4711

Identifiers are replicated / IDもコピーされる

GTIDはバイナリログにて、それぞれのトランザクションの前に記録されます。
例:
http://2.bp.blogspot.com/-voF9rqzdV0k/UGZHwzIZDeI/AAAAAAAAADg/_9X-eKz9S98/s1600/8-binlog-with-gtids.png

バイナリログの内容は、GTIDを含めてスレーブに転送されます。スレーブはこのGTIDを読み、スレーブでコミットを行っても同じGTIDを維持します。そのため、スレーブでは新たにGTIDを生成することはありません。スレーブとマスターでは、GTID生成の観点からはコミット時の挙動が異なります。(より正確に言うと、スレーブのスレッドとクライアント処理をするスレッドでは挙動が違う) スレーブ内部での詳細なメカニズムは重要なため、次のブログポストにて詳解します。

Global Transaction Identifiers in Action / GTIDの実際の使われ方

実行済みのGTIDは、gtid_donegtid_executedというグローバル変数で確認できます。この変数はMySQL 5.6で追加された参照専用の変数です。gtid_donegtid_executedはそのサーバでコミットされたGTIDの「範囲」を文字列で格納しています。例えば、下記のIDがトランザクションによって生成されたとします。

    0EB3E4DB-4C31-42E6-9F55-EEBBD608511C:1
    0EB3E4DB-4C31-42E6-9F55-EEBBD608511C:2
    4D8B564F-03F4-4975-856A-0E65C3105328:1
    0EB3E4DB-4C31-42E6-9F55-EEBBD608511C:3
    4D8B564F-03F4-4975-856A-0E65C3105328:2

するとgtid_donegtid_executedの値は以下のようになります。

    "0EB3E4DB-4C31-42E6-9F55-EEBBD608511C:1-3,
    4D8B564F-03F4-4975-856A-0E65C3105328:1-2"

その他の例:

mysql> SELECT @@GLOBAL.GTID_EXECUTED;
+------------------------+
| @@GLOBAL.GTID_EXECUTED |
+------------------------+
|                        |
+------------------------+

mysql> CREATE TABLE tbl (a INT);
mysql> SELECT @@GLOBAL.GTID_EXECUTED;
+----------------------------------------+
| @@GLOBAL.GTID_EXECUTED                 |
+----------------------------------------+
| 4D8B564F-03F4-4975-856A-0E65C3105328:1 |
+----------------------------------------+
mysql> INSERT INTO tbl VALUES (1);
mysql> INSERT INTO tbl VALUES (2);
mysql> INSERT INTO tbl VALUES (3);
mysql> SELECT @@GLOBAL.GTID_EXECUTED;
+------------------------------------------+
| @@GLOBAL.GTID_EXECUTED                   |
+------------------------------------------+
| 4D8B564F-03F4-4975-856A-0E65C3105328:1-4 |
+------------------------------------------+

この変数は、スレーブがマスターに追いついているかどうか、追いついていない場合にはどのトランザクションが未実行かを確認するためにも使えます。

master> SELECT @@GLOBAL.GTID_EXECUTED;
+------------------------------------------------+
| @@GLOBAL.GTID_EXECUTED                         |
+------------------------------------------------+
| 4D8B564F-03F4-4975-856A-0E65C3105328:1-1000000 |
+------------------------------------------------+
slave> SELECT @@GLOBAL.GTID_EXECUTED;
+-----------------------------------------------+
| @@GLOBAL.GTID_EXECUTED                        |
+-----------------------------------------------+
| 4D8B564F-03F4-4975-856A-0E65C3105328:1-999999 |
+-----------------------------------------------+

この場合には、マスタで行われたトランザクションの4D8B564F-03F4-4975-856A-0E65C3105328:1000000がスレーブではまだ実行されていないことを表します。必要な場合には、mysqlbinlogコマンドなどを使って、このトランザクションの内容を確認できます。

The Last Ingredient: New Replication Protocol / 新しいレプリケーションプロトコル

ここまでGTIDがどのように生成され、レプリケーション構成の中でどのように展開されるかを見てきました。続いてはフェールオーバーのための新しい重要な要素、改良されたレプリケーションを見ていきます。

プロトコル:従来はスレーブがマスターに接続すると、バイナリログ名とオフセット(バイナリログのポジション)をリクエストし、それ以降全てを転送していました。新しいプロトコルでは、
1. スレーブがマスターに接続すると、スレーブで実行&コミット済みのGTIDの範囲をマスターに送信する
2. マスターは、「それ以外」のトランザクションを全てスレーブに渡す ※スレーブから送られたGTID以降ではなく、スレーブで実行されていないトランザクション全て

:下記が新しいレプリケーションプロトコルの例
http://4.bp.blogspot.com/-xHF6fk3in_c/UGZHxLtuqcI/AAAAAAAAADo/eLObx289fGs/s1600/9-new-protocol.png
ここではバイナリログの内容を個別に表現しています。特定のSQLが1つのトランザクションで実行されていますがここでは重要ではありません。説明をシンプルにしたかっただけで、実際には複数のクエリが1つのトランザクションに含まれることが多いでしょう。またUUIDの数字そのものなども重要ではないので、GTIDは単に省略してid1, id2などとしてあります。
この例では、Cは“id1...id2”をBに送り、Bはid3のtrx3をCに送っています。もっとトランザクション続けばBに以降を転送し続けます。

SQL:以下のSQL文で新しいプロトコルを利用することを設定できます。

CHANGE MASTER TO MASTER_AUTO_POSITION = 1;

重要なポイントは、手動でGTIDを指定する必要は全く無い点です。スレーブは自動的に実行済みのGTIDをマスターに送信します。MASTER_AUTO_POSITION = 1を設定した場合は、MASTER_LOG_FILEまたはMASTER_LOG_POSを設定することはできません。

Failover / フェールオーバー

GTIDを使ってフェールオーバーを行う準備ができました。
ツリー型:最初の例の場合。先ほどの絵にバイナリログの情報を追加しました。
http://1.bp.blogspot.com/-4ey5LjLEFOg/UH5vD2L30dI/AAAAAAAAAFI/PYhRnBzHXw0/s1600/10b-tree-failover-new-protocol-fixed.png
この絵のように、マスターでは3つのトランザクションが実行されていて、Bでは全てが適用済み、Cには1つだけが転適用された状態だします。そしてAで障害が起きたとします。この場合にはBを新しいマスターとし、CをBのスレーブとします。新しいレプリケーションプロトコルを使うと、Cはid1をBに送ると、Bはid2のtrx2(およびそれ以降にBでコミットされたトランザクション)をCに送ります。

Circle topology(略)

Summary / まとめ

シームレスなフェールオーバーを可能とするため、MySQL 5.6にGTIDが導入されました。GTIDはそのトランザクションが初めてコミットされた時に生成され、別のサーバにレプリケートされた場合には同じIDが維持されます。新しいレプリケーションプロトコルは、フェールオーバーをほぼ自動化します。データベース管理者がGTIDを知っておく必要はありません。管理者が行うべきはどれが新しいマスターかをスレーブに知らせることです。監視で重要になってくるのは@@GLOBAL.GTID_DONE @@GLOBAL.GTID_EXECUTEDです。

抄訳 InfoWorld: MySQL users caution against NoSQL fad

InfoWorldの記事に興味深い記事があったので抄訳。
タイトルは「MySQL users caution against NoSQL fad」で訳すと「MySQLユーザがNoSQLブームに警鐘を鳴らす」という感じでしょうか?2012年9月のMySQL Connect 2012でのパネルディスカッションの内容などをもとに、NoSQLテクノロジーは本当に必要なのかという疑問を提示しています。

以下は抄訳なので詳細は原文をお確かめください。
MySQL users caution against NoSQL fad | InfoWorld

Paypalの例

PayPalのチーフアーキテクトは「A lot of people think they have a big data problem, and a lot of times they don't,」「多くの人が"ビッグデータ"の問題を抱えていると考えているが、実際には多くの場合は問題では無い」として、「"ビッグデータ"ソリューションがかっこよく見えているだけだ」としています。

Paypalでは100TBのストレージを使って全世界の支払いデータの管理を行っています。一度書き込まれた支払いの情報は1秒以内に全世界のどこからでも参照できる必要があります。PaypalではAmazon Web Servicesの6拠点にデータを分散させてこの要件を実現しています。PayPalでは完全な高可用性はもちろん、高い拡張性を理由にMySQL Clusterを選択しています。

Twitterの例

MySQL導入事例
Tiwtterでは1億4000万以上のアクティブユーザが毎日4億以上のメッセージをツイートしています。それぞれのメッセージぶはインデックス化およびメタデータによる属性の設定なども行われます。TwitterではMySQL 5.5.を改変した独自バージョンを使用し、6人のデータベース管理者が数千台のMySQLサーバを管理しています。NoSQLではなくMySQLを利用している理由は、1) MySQLの内部構造を含め拡張性を持たせるノウハウを多く持っている 2) バグを修正しMySQLの次のバージョンに含める方法を分かっている 3) わずかなチューニングで多くのクエリを処理できる 4) InnoDBはデータを失う心配が無い としています。

多くのNoSQLベンダがNoSQLの方がRDBMSより速いとしていますが、Tiwtterでは「Often that is not true,」「多くの場合そうではない」との見解を示しています。独自のシャーディングおよびレプリケーション機能をGizzardというソフトウェアにしていますが、これもMySQLをバックエンドのデータ管理に利用しています。

Playful Playの例

MySQL導入事例
Playful Playはメキシコを拠点とするオンラインゲーム企業で、最近急激なユーザの伸びを見せています。メキシコの長寿コメディ番組"El Chavo"をベースにしたゲームが3百万ユーザを超える大ヒットとなり、毎日3万ユーザが新規に利用しています。当初はコミュニティ版のMySQL Clusterで構築していましたが、劇的なユーザの増加に「we got very scared」「恐ろしくなった」ため、オラクルのサポートを利用しパフォーマンスの問題などを解消しました。

現在は24サーバのMySQL Cluster Carrier Grade Editionを、ユーザの属性情報、アバターのプロフィール、および広告データを格納しています。12台は本番運用に利用し、残りはマーケティング用の分析、開発用途などに利用しています。現在は番組が放送されたラテンアメリカやトルコ、スペイン、フィリピンなどへの海外展開のために、1億ユーザに耐えられるインフラ作りを行っています。


MySQL ClusterもMySQLサーバも引き続き大規模なWebでも幅広くご利用いただいており、MySQL 5.6によってさらに強化されていきます!

MySQL Connect 2012での発表事項

日本オラクル広報室長の[twitter:@Wagamatt]が連続ツイートしてくれましたが、米国でのMySQL Connect 2012にて多くの発表がありましたので要点をまとめておきます。
10月後半にMySQL Tech Tourとしてこれらについてのセミナーを開催予定ですので是非ご参加ください。MySQL Tech Tourのお申し込みはこちらから

MySQL 5.6 RCリリース

MySQL 5.6での主な改善点は以下の5つのカテゴリです。

まとめ記事はこちらです(英語)。


個人的に注目している改善点は以下の通りです。

RCより前の改善点の概要はオープンソースカンファレンスでの講演資料や [twitter:@nippondanji]のブログを参照してください。

MySQL Cluster 7.3

まとめ記事はこちらです(英語)。

MySQL Clusterは共有ディスクを必要としないActive-Activeなデータベースクラスタです。また、トランザクション対応キーバリューデータストアとしての利用も広がっています。今回のDMRおよびLabsでの新しい機能は以下の通りです。

商用版のMySQL Enterprise Editionの機能追加

サポートサービス拡張機能を提供するMySQL Enterprise Editionにも新たな機能が加わっています。

  • Solaris Clusterのサポート開始
    • ミッションクリティカルなシステムで多数の実績があり、小規模なクラスタシステムからデータセンターをまたいだ大規模なクラスタリング環境までをサポートする、Oracle Solaris Clusterとの組み合わせも正式にサポート対象となりました。
    • Oracle Solaris Cluster

MySQL Migration Wizard登場

これ、本当にMySQL Workbenchのマイナーバージョンアップの一部でいいの?

メンテナンスを含めて開発終了となっていたMySQL Migration Toolkitの後継にあたる、新しいマイグレーションツールがリリースされました。名称はMigration Wizardで、独立したソフトウェアでは無くMySQL Workbenchの一部機能となっています。ライセンスは「もちろん」GPLです。これで以前のMySQL GUI Toolsの全ての機能が戻ってきたことになります。ダウンロードはこちらから。

Migration Wizardの具体的なマイグレーション元の第一弾としては、Microsoft SQL Serverがサポートされています。またODBCをサポートしているため、他のデータベースからのマイグレーションも可能です。動作環境はWindows, Mac OS X および Linuxです。但しWindowsでは.Netフレームワークなどが別途必要となりますのでご注意ください。

Migration Wizardの起動方法はMySQL Utilitiesの起動と同じく、起動にはMySQL Workbenchのメニューの【Database】から【Migrate. . .】か、MySQL Workbenchメイン画面の右上のアイコン【Database Migration】を選びます。ディスプレイの解像度(特に横)が低い場合などはこの【Database Migration】のアイコンが表示されないこともあるため、▽のプルダウンボタンから選ぶ必要があります。


開発チームのブログ記事ではSQL Server 2000からMySQL 5.5へのマイグレーションを紹介しています。

準備作業は以下の通りです。

  • マイグレーション元のデータベース用のODBCドライバがインストールされていること
  • メニューの【Plugins】から【Start ODBC Administrator】から

ODBCデータソースアドミニストレータを起動してドライバの有無を確認
Windows ODBC Data Source Administrator


マイグレーション作業の流れは以下の通りです。
1. メイン画面右側の【Database Migration】アイコン、またはメニューの【Database】から【Migrate】を選択
The initial screen of MySQL Workbench
2. 新しいタブにMigration Wizardが表示される。【Start Migration】ボタンで次に進む
Overview Page
3. マイグレーション元のデータベースおよび接続方法を選択する
Source Selection Page
4. ターゲットのMySQLサーバを選択する
Target connection parameters
5. 【Next】ボタンを押すとマイグレーション元のデータベースに接続しスキーマを抽出
Fetch schemata list page
6. マイグレーション元のスキーマを選択
Schemata Selection Page
7. 「リバースエンジニアリング」としてテーブル名や列名、外部キーやインデックスなどを検索
Reverse Engineer Progress
8. マイグレーションするデータベースオブジェクトを選択
Source Objects Page
9. 一部のオブジェクトを選択する場合は【Show Selection】ボタンを押す
Source Objects Page Expanded
10. データ型などのマッピングをテスト
Manual Editing Page
11. 【Show Code and Messages】を押すと、生成されたコードの確認と編集が可能
Manual Editing Page Expanded
12. 右上のViewのプルダウンから【Column Mappings】を選ぶと列のマッピングが確認と編集が可能
Column Mappings
13. スキーマを直接ターゲットのMySQLにコピーするか、ファイルに書き出すかを選択
Target Creation Options Page
14. ターゲットのMySQLに接続し、スキーマを作成
Create Schemata Progress Page
15. 作成されたスキーマの確認。エラーがあった場合などはOutput Messagesに出力される
Create Target Results Page
16. データを直接ターゲットのMySQLにコピーするか、ファイルに書き出すかを選択
Data Transfer Setup Page
17. 実際にデータを移行
Bulk Data Transfer Page
18. ウィザードの最終ページにマイグレーション結果のログが出力される
Migration Report Page
19. SQL Editorにてスキーマやデータを確認
A query on the MySQL migrated database
21. メイン画面中央下の【Create EER Model From Existing Database】からER図を作成
EER Model for the Migrated Database

便利なスクリプト集 MySQL Utilities

実は1.0.0が2010年12月にリリースされていたのに全く知名度の無い"MySQL Utilities"。実は便利な機能が複数用意されているので、スクリプトを手作りしなくても済む可能性大です。またリリースに向けて新たなマイルストーンリリースが出てきたMySQL 5.6でのレプリケーションの追加機能と組み合わせる便利機能もあります。

MySQL UtilitiesはPythonで書かれたスクリプト集で、MySQL Workbenchに同梱されて配布されています。ライセンスは「もちろん」GPLです。2012年7月上旬時点での最新版は1.0.5です。また実行可能なスクリプトの他に、ライブラリとして細かな機能が用意されているため、独自のスクリプト作成にも役立ちます。


起動にはMySQL Workbenchのメニューの【Plugins】から【Start Shell for MySQL Utilities】か、MySQL Workbenchメイン画面の右上のアイコン【MySQL Utilities】を選びます。コンソールまたはコマンドプロンプトが起動し、MySQL Utilitiesの各スクリプトが使えるようになります。

MySQL Utilitiesの知名度が足りない原因の一つに、起動方法のわかりにくさが挙げられます。特に問題なのがアイコンで、ディスプレイの解像度(特に横)が低い場合などはこの【MySQL Utilities】のアイコンが表示されず、▽のプルダウンボタンを選ぶ必要があります。環境によっては▽のプルダウンあと、さらに【Next】ボタンを押さないとこのアイコンにたどり着かない場合があります。またMac OS X上ではコンソールのウィンドウがバックグラウンドで開いてしまい、起動していないように見えるのでウィンドウを切り替えてから利用してください。
▽のプルダウンボタンを押してもアイコンが見えない
【Next】ボタンを押した後



MySQL Utilitiesはスクリプトごとにオプションが異なりますが、1つポイントになるのが対象サーバの指定方法です。通常のMySQLクライアントプログラム(mysqlやmysqldumpなど)とは書式が異なっています。

mysqldump -uユーザ -pパスワード -hホスト名 -Pポート番号 …
mysqldump --user=ユーザ --password=パスワード --host=ホスト名 -port=ポート番号 ...
mysqldbexport --server=ユーザ:パスワード@ホスト名:ポート番号 ... 


スクリプトの機能はマニュアル(MySQL WorkbenchのマニュアルのChapter 13)の実行例を見ていただくとイメージしやすいかと思います。



データおよびデータベース管理

mysqldbcompare 同一サーバ内または2つのサーバ間のデータや定義の比較
mysqldbcopy 別のサーバにデータベースをコピー
mysqldbexport データとメタデータをエクスポート
mysqldbimport データとメタデータをインスポート
mysqldiff 2つのサーバ間のテーブルなどオブジェクトの定義を比較

サーバ運用各種

mysqldiskusage デーブルおよびデータファイルのサイズを表示
mysqlindexcheck インデックスの重複をチェック
mysqlmetagrep テーブル定義などのメタデータgrep (正規表現利用可)
mysqlprocgrep INFORMATION_SCHEMA.PROCESSLISTをgrep (正規表現利用可)
mysqluserclone 別のサーバにユーザアカウントををコピー

高可用性関連

mysqlreplicate レプリケーションを設定
mysqlrplcheck レプリケーションが正しく設定されているかの確認
mysqlrplshow レプリケーショントポロジ(親子関係)を図示
mysqlfailover レプリケーションの自動フェールオーバー※
switchover 手動でのレプリケーションの切り替え※
mysqlrpladmin レプリケーションの各種管理※※

MySQL 5.6.5以降のみ対応
※※ 一部機能はMySQL 5.6.5以降のみ対応

サーバ定義関連

mysqlserverclone 既存のMySQLサーバのコピーを作成
mysqlserverinfo サーバの稼働状況を表示


mysqlfailover, switchoverおよびmysqlrpladminは、MySQL 5.6.5で追加になったGTID (Global Transaction ID)を利用していますが、他のコマンドはMySQL 5.5でも利用可能です。

GTID:

5.6.5から実装された、バイナリログに書かれたトランザクション単位にユニークなIDを割り当てる機能。レプリケーション環境での状況の確認やスレーブ間での進捗の比較が簡単になります。GTIDの利用には以下のオプションの設定が必要です。

  • gtid_mode=ON - GTIDを有効にする
  • log-slave-updates - スレーブをカスケード(多段)構成にする際に必要となる設定
  • disable-gtid-unsafe-statements - GTID非対応のクエリの利用を制限。5.6.6時点では、1)トランザクション内でのCREATE TEMPORARY TABLE、2)トランザクション非対応テーブルへの全ての更新、3)CREATE TABLE ... SELECT

ちなみに、なぜMySQL UtilitiesはPythonで書かれていてPHP, PerlRubyやじゃないんだという疑問は開発チームにも多数届いているようですが、「どの言語で書いても他の言語の使い手から文句が出るから」という回答をしていたようです(笑)