バージョン違いMySQLの同居

同じバージョンのMySQLを2台同じサーバーに入れたりというのは開発環境でやったことがあるのですが、双方とも自動起動してバージョン違いかつ文字コード違いという環境は初めて入れた。結論としては自動起動スクリプトがまるで複数導入を想定していないというのが分かったくらいかな。

やってみた構成はこんな感じ。
  • rpm版同士での複数インストール
    これは普通に競合するのでNG
  • 既存のMySQLクライアントとPHP-MySQLコネクタを残して、MySQL公式サイトのrpm最新版(Serverのみ)をインストール
    これも競合。MySQL公式サイトのものはServerとClientで2つに分けているが、RedHat公式のMySQLはServerとClientとその両方で使う無印パッケージの3つ分かれ、無印とMySQL公式のパッケージで競合を起こす。
  • 既存はrpm版で別途ソース版を入れる
    これは問題なし、自動起動スクリプトは改造が必要
  • 既存がソース版で別途インストールもソース版
    問題は無いがソース版同士なので全ての設定を別に分ける必要が出てくる。自動起動スクリプトは改造が必要。
自動起動スクリプトの改造が必要なのは、configureの設定内容を無視しているのでそのまま使えばデフォルトの構造でmy.cnfやpidファイル、sockファイルを探しに行くという恐ろしいワナがある。結局自動起動スクリプト上のmysql_safeコマンドの行に–defaults-file=[my.cnfのパス]で設定が必要。ちなみにこのオプションは最初に記述しないとエラーになります。他にはDBの初期化(mysql_install_db)をするときに既存のDBを破壊しないように念のためバックアップを取った上でオプションでdatadirやdefaults-fileを設定し回避すること。これは理由がわからないのですがスレーブ用に構築する予定のDBで初期化するときに最初からmy.cnfよりbin-logを抜いていたらエラーになった。これは初期化にはバイナリログが必要だったのか、中途半端なコメントがまずかったのかは不明。別に初期化の時にバイナリログが出されてもたいしたこと無いので別に良いのですけどね。
参考
またレプリケーションも本格的に負荷分散しようとしたら参照系で不要なDBやテーブルを持ってきたくないという事がありました。こちらの設定はスレーブ側のmy.cnfの[mysqld]内に
replicate-do-table=dbname.table
replicate-do-db=dbname
といった感じで追記するだけ。
また文字コードの設定で[mysqld]内に
default-character-set = utf8
だけでなく
skip-character-set-client-handshake
を設定するとPHPから接続したときにいちいち「SET NAMES」を設定しなくても良くなるし、他のセクションにdefault-character-setを入れなくても文字コードが統一される(status;やshow variablesで確認)。
[MySQL] 特定データベース、特定テーブルを指定したレプリケーション設定 | 半袖野郎 blog.hansode.org
あと大きなバッチを使うときに気になるのがメモリ使用量なのですが、折角1行ずつ取り出すのに一斉に配列に入れようとするのはセンス無さ過ぎで見つけ次第指導するレベルなのですが、また全件必要でないのにどうせ詮索スピード変わらないからという理由でLIMITを使わないのもメモリの事を考えてない証拠なのでこれもダメ、でもまさかmysql_query関数の結果が一旦全部メモリにキャッシュされるとは思わなかった。PHP上ではどう見てもメモリが溜まるような処理を書いてないのにメモリ不足になるのはこれのせいだった。そのときはmysql_unbuffered_queryを使いましょう。mysql_unbuffered_queryの制約としてはmysql_data_seekが使えないことや全ての行をフェッチする必要があるという事なので件数の絞込みはしっかりLIMITで設定しましょう。スピードは多分遅くなると思いますがバッチ等では消費メモリの上限を抑えられない方が問題なので。
PHP:SQLクエリのメモリ消費量を抑える:mysql_unbuffered_query