MySQL のレプリケーションでリレーログのイベントを実行する際の文字セットって?

なんだか、よくわからない。

基本的に、クライアントとサーバの文字セットを同じにして扱う事しかしてこなかったので、それらを別にして skip-character-set-client-handshake しないケースでレプリケーションがどうなるかを、真剣に考えた事がありませんでした。

そういうケースでも、レプリケーションは問題なく行われる(マスタと同一の状態を保てる)のでしょうか。

例えば、以下の様な場合。

client(latin1)->data(utf8)->server[master](utf8)
server[master](utf8)->server[slave](utf8)
relay-log(utf8)->server[slave]

latin1 な client から utf8 な文字列を含む SQL クエリを utf8 な server[master] に送信。

skip-character-set-client-handshake を有効にしていないため、 server[master] であれこれする時に uf8 の文字列を latin1 から utf8 に変換する(from_latin1_to_utf8(str_utf8)なイメージ)。

server[master] のバイナリログには、変換される前の、client から送信されたコマンドそのままが記録される。

レプリケーションを行っているため、server[master] のバイナリログを server[slave] が受け取り、リレーログに書き込む。

server[slave] のリレーログは、server[master] のバイナリログと同じ。

server[slave] の SQL スレッドが、リレーログに記録されたイベントを実行する(ステートメントベース)。

イベントを実行するときの character_set_client および collation_connection および collation_server は、server[slave] のグローバル変数が利用される。

という流れを想像していますが、大分嘘がある様な気がします。

まず、バイナリログへの記録には、client-server 間の文字セットの違いに起因する変換処理が介在せず、クライアントから送られたデータそのままを記録する、というのが本当か知りません。イベントに伴うセッション変数の値を記録していたりするのは知っているので、多分、これでいいだろうとは思っています。が、ドキュメントを確認していません。

リレーログに記録されているイベントを実行する際に、client-server[master] 間で使われた文字セットの関係は、復元されるのでしょうか。されない場合、client-server 間の関係で言うと、それぞれどのような値が使われるのでしょうか。リレーログのイベント実行は、client-server の様な関係で実行されるわけではなかったりするのでしょうか。

ちょっとだけ、ソースコードを読んでみましたが、exec_relay_log_event(...)からset_slave_thread_default_charset(...)にたどり着いて、そこから先がよく分かりません。グローバルな文字セットを標準で使う事は何となく分かる気がしますが、ログに記録されているセッション変数を復元してそれを使うのかどうかが分かりません。ちゃんと読めば分かりそうな気がしますが、本当にちょっと見ただけの状況です。

公式ドキュメントを読んだら、この件に関する記述があったりしますかね。実験で挙動を見れば、どうなるかは分かりそうですが、それはそれとして、仕様的な話を知りたいところです。まずは、公式ドキュメントのレプリケーションやバイナリログ、文字セットに関する部分を一通り読むところからスタートでしょうか。

と、まあ、そんな感じで、さっぱりです。

プロフィール

このブログ記事について

このページは、koshigoeが2008年12月11日 00:40に書いたブログ記事です。

ひとつ前のブログ記事は「ひとまず PHPSpec」です。

次のブログ記事は「ZendFramework と Smarty」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。