Go to the first, previous, next, last section, table of contents.


21 Solving some common problems with MySQL

21.1 更新ログを使用したデータベースの複製

Now that master-slave internal replication is available starting in 3.23.15, this is the recommended way. However, it is still possible to replicate a database by using the update log. 「21.3 更新ログ」節参照. これは、一つのデータベースがマスター(主)として動作ふるまっており (全てのデータ変更がここで行われます)、かつ、一つ以上の他のサーバーがスレーブ(従)と して動作していることを要求します。 スレーブを更新するには mysql < update_log を実行するだけです。 スレーブデータベースのホスト、ユーザー、パスワードをコマンドのオプションに与え、 マスターから取得した更新ログを入力に使用します。

もし、テーブルからなにも削除しない場合、 TIMESTAMP フィールドを使用すれば、 最後の複製時以後に、新規に挿入されたものや変更されたものだけを ミラーサーバーにコピーできます。(最後の複製を行った時間と比較すれば抽出できます)

更新ログ(削除のため)とタイムスタンプ(両側で)の両方を使用する2つの方法の 更新システムを作ることができます。しかしこの場合は、同じデータが両側で変 更された時に、あなたが衝突を操作できなければなりません。あなたはおそらく 何が更新されたかを決定するのを助けるために、古いバージョンを保持したいで しょう。

この時行う複製には SQL ステートメントで行われるため、データベースを更新す るステートメント中で次の関数は使ってはいけません。これらは他の コピー元のサーバとは違う値を返すからです:

全ての時刻関数は、必要な場合にミラーにタイムスタンプを送るようにして、安 全に使用できます。LAST_INSERT_ID() も安全に使用できます。

21.2 データベースのバックアップ

MySQL テーブルはファイルとして格納されるため、バックアップを行 うのは簡単です。矛盾のないバックアップを得るためには、LOCK TABLES を関連するテーブルで行ってください。 「7.27 LOCK TABLES/UNLOCK TABLES 構文」節参照. 読み込みロックだ けが必要なので、そのテーブルでデータベースディレクトリのファイルのコピー が行われている間も、他のスレッドはクエリを継続できます。もしくは、テーブルを SQL レベルでバックアップしたいのであれば、SELECT INTO OUTFILE を使 用できます。

他の方法は mysqldump プログラムを使用することです:

  1. フルバックアップをとるには:
    shell> mysqldump --tab=/path/to/some/dir --opt --full
    
    若しサーバーがいっさいデータの変更をしないのであれば、 単に全てのテーブルファイル(`*.frm', `*.MYD', `*.MYI' files)を コピーするだけでも構いません。 The script mysqlhotcopy does use this method.
  2. mysqld を止め、そして --log-update[=file_name] オプションをつけて起動します。 「21.3 更新ログ」節参照. ログファイルは、 mysqldump 実行後に行われたデータベースの変更を 複製するための情報を与えてくれます。

もしリストアをしなければならない場合、まず最初に myisamchk -r を実行して テーブルの修復を試みてください。 ほとんどの場合、99.9% 修復はできるはずです。 もし myisamchk が失敗した場合、以下のようにします: (This will only work if you have started MySQL with --log-update. 「21.3 更新ログ」節参照.)

  1. オリジナルの mysqldump バックアップデータをリストアします。
  2. 以下のコマンドのようにして、更新ログに記録されている変更を適用します。
    shell> ls -1 -t -r hostname.[0-9]* | xargs cat | mysql
    

ls は、全ての更新ログファイルを正しい順で得るために行われます。

SELECT * INTO OUTFILE 'file_name' FROM tbl_name での選択的バックアップと LOAD DATA FROM INFILE 'file_name' REPLACE ... でのリストアを行う こともできます。重複レコードを避けるためには、テーブル内に PRIMARY KEY or a UNIQUE が必要です。REPLACE は、'重複インデックス' 衝突があった場合、 新しいレコードを挿入する時に古いレコードが新しいものに置き換えられることを意味します。

21.3 更新ログ

--log-update=file_nameオプションを使用してmysqldを起動すると、 データを更新した全てのSQLコマンドをログファイルに書きます。 もし file_name が与えられなかった場合は、ホスト名がデフォルトで使用されます。 もし file_name にディレクトリパスが含まれなかった場合は、 このファイルはデータディレクトリに書かれます。 もし file_name が拡張を持たなかったなら、mysqldfile_name.# という形でログファイルを作成します。 このログファイルはデータディレクトリにかかれ、 その名前は file_name.# という形式の名前になっています。

#mysqladmin refreshmysqladmin flush-logs を実行する度に、 あるいは FLUSH LOGS 構文を実行したり、サーバーをリスタートする度に 自動的に増える数字です。

もし --log-l オプションを使用した場合、ログファイルの名前は mysqld は全部のログを `hostname.log' に書き出します。 この場合、リスタートやりフレッシュを行っても新しくログファイルを作りません。 (一度クローズして再度オープンしますが。) デフォルトでは、mysql.server スクリプトは -l オプションを付加して MySQL サーバーを起動します。 もし MySQL のパフォーマンスをあげて本番環境などで使用したい場合、 mysql.server スクリプトから -l オプションを外してください。

更新ログは、実際に更新されたデータのステートメントだけを書くため、きびきびと動作します。 WHERE を使用した UPDATEDELETE で結果が得られなかった場合、 ログは書き出されません。 すでにセットされている値に、もう一度項目を更新するような UPDATE もスキップされます。

ログファイルの更新に従ってデータベースを更新したい場合は、次を行います (更新ログファイル名を `file_name.#' と仮定します):

shell> ls -1 -t -r file_name.[0-9]* | xargs cat | mysql

ls は全てのログファイルを正しく並べるために使用しています。

これは、クラッシュ後にバックアップした状態まで戻りたい、あるいは、 バックアップした後からクラッシュするまでの間のデータの更新を行いたい、 そんな場合に使えます。

ログは違うホストのデータベースのミラーやマスターデータベースの複製を作る場合にも利用できます。 「11 Replication in MySQL」節参照.

21.4 同一マシン上に複数の MySQL サーバーを走らせる

同じマシン上で複数のサーバーを走らせたい場合があります。 例えば、すでに存在しているサーバーはそのままにしておいて、新しい MySQL をテストしたい場合や、 あるいは、インターネットプロバイダーを営んでいて、MySQL をそれぞれの顧客用に提供したい場合など。

複数のサーバーをたちあげる場合、簡単な方法として、 TCP/IP ポート、ソケットファイルを変えて、サーバーをコンパイルする方法があります。

そでに走っているサーバーがデフォルトのポート番号とソケットファイルで動作しているとします。 新しくサーバーを作るには、以下のように configure します:

shell> ./configure  --with-tcp-port=port_number \
             --with-unix-socket=file_name \
             --prefix=/usr/local/mysql-3.22.9

port_numberfile_name には、デフォルトのポート番号、ソケットファイルとは違うものを指定します。 そして --prefix を、すでに走っている MySQL のインストール先とは違うディレクトリーに指定します。

現在走っている MySQL サーバーのソケットとポートを知るには、以下のようにします:

shell> mysqladmin -h hostname --port=port_number variables

あなたが使用しているポートに MySQL サーバーが走っていれば、 これは変更可能な MySQL 変数を(ソケットファイルの名前も含んで)出力します。

立ち上げスクリプト(おそらく `mysql.server' ファイル)を編集して 複数の MySQL サーバーを立ちあげても構いません。

この場合、 MySQL サーバーを再コンパイルする必要はありません。 safe_mysqld のオプションを指定してサーバーを起動すれば、ポートとソケットを変更できます:

shell> /path/to/safe_mysqld --socket=file-name --port=port_number

もし、他のサーバーがロギングを行っているディレクトリと同じデータベースディレクトリを、 新しいサーバーで使用するのであれば、ログファイルの名前を指定すべきです。 ( safe_mysqld--log--log-update を指定する) そうしないと、両方のサーバーが同じログファイルに書き込もうとするからです。

Warning: 通常、二つサーバーに同じデータベースを操作させてはいけません! もし使用している OS が fault-free system locking をサポートしていないと、 これは悲惨なことになるでしょう!

もし二つ目のサーバーに違うデータベースディレクトリを使用させたい場合、 safe_mysqld--datadir=path オプションを指定します。

shell> /path/to/safe_mysqld --datadir=/new/path/to/datadir \
                --socket=file-name --port=file-name

もし違うポートで走っている MySQL サーバーに、 これまた違うポートを使用するように作られたクライアントから接続したい場合、 以下のようにします:


Go to the first, previous, next, last section, table of contents.