タグ別アーカイブ: mysqldump

複数人開発の時にデータベースの同期をうまく取る方法

最近「意外に若かったんだね」と言われるようになりました、その言葉の指すところについては考えないようにしています岡田洋一ですコンニチハ。

さて、僕はしばらくチームで開発を行っています。大人数というわけでも無く、2〜3人での小規模プロジェクトチームです。少人数制のチームではありがちで、僕以外のメンバーもプログラム〜インフラ周りも修正することが多く、データベースのテーブル構造を修正することが各自にありえます。

さてそんなときにデータベースの同期を取る方法について考えてみました。

現状はテーブルのCREATE分を出力させ、プロジェクトのwikiに書き込んでいます。

wikiは変更情報を保存しますので、ある程度のバージョン管理ができました。が、いかんせん「出力、編集、保存、確認、伝達、適用」と、修正内容をチーム内で共有するためのステップが多いのです。少人数チームでステップが多いのは良くないですね。素早さこそがウリですから。

次に「テーブルの差分になるALTERのみを書く」ということについて勘案しました。が、こちらも開発を兼ねているため、テーブルの変更となるALTER分はそこそこの数が出てしまい、すべてのALTERを記録して適用することは面倒となりました。素早さがなくなってしまいます。

 

というわけで、現在のテーブル情報を書き出しつつバージョン管理システムで共有、という手段にしました。

現在プロジェクトはSVNで管理されていたので、テーブル情報のみをファイルに書き出してコミット、それを手元へ適用という手段をとりました。ちなみにデータベースはMySQLです。

テーブル情報のみを書き出す為に必要なコードは

shell> mysqldump -h mysqlhost -u user -ppassword --no-data target_schema | sed 's/ AUTO_INCREMENT=[0-9]*//' > tables.sql

shell> svn commit tables.sql -m 'update table sql.'

となりました。mysqlのホスト名、ユーザ名、パスワード、対象スキーマは読み替えて下さい。パスワードはナシにするとプロンプトで聞いてきます。

パイプでsedに渡してAUTO_INCREMENTを消しています。

最後にこの出力をファイルに書き出して、コミットして共有します。

 

これだと差分をうまく見ることができるので便利ですね!

wordpressでリモートにある環境にデータベースを転送したい

はめじに

wordpressでリモートにある環境にデータベースを転送したい。転送というか同期というか。

通常の環境であれば管理者メニューからエクスポート > インポートとすればすむ話なのだけれど、今回はちょっと変わった事情があった。

その条件ってのは下記の通り

  • 手元のサーバにあるワードプレスのデータベースの一部(コメントとかは上書きしないようにする)をリモートサーバに転送したい
  • リモートサーバにはsshでログイン可能
  • テータベースの一部のうち、post_metaにあるmeta_keyがviewsは上書きしたくない
  • 転送するのは一日に一回ぐらいのそこそこのペースで転送したい

リモートホストにsshでログインできるのでsshとパイプを使ったワンライナーでやってしまおう的な。

またpost_metaのテーブルはちょっとやっかい。今回利用しているプラグインでWP-PostViewsという閲覧数を保管するプラグインがある。これは閲覧数をpost_metaにmeta_key = viewsで管理している。だからそこをハズしたい。

キャプチャ4

というわけでさっくり

mysqldump –h localdbhost –u localuser –plocaldbpassword  --add-drop-table wpdbname wp_options wp_posts wp_postmeta wp_term_relationships wp_term_taxonomy wp_terms wp_users wp_usermeta | ssh [email protected] mysql -f -h remotedbhost -u remotedbuser –premotedbpassword  remotewpdb

これでひとまずpost_meta以外はいけた。

データがちょっと複雑なpost_meta

post_metaに関してはmysqldumpにwhere句が使えるらしいので使ってみる。

次にpost_metaをうまく通してやるためにオプションを調整してやる。

mysqldump –h localdbhost –u localuser –plocaldbpassword   --add-drop-table=false --extended-insert=false --where="meta_key!='views'" mysqldump –h localdbhost –u localuser –plocaldbpassword wp_postmeta  |  ssh [email protected] mysql -f -h remotedbhost -u remotedbuser –premotedbpassword remotewpdb

キャプチャ

--add-drop-table=false

これは対象テーブルのdrop table – if exists文を出力に含めないようにするためのオプション。

基本的にはテーブルがあるっていう前提なのでcreate-infoごといらないかもしれない。(create文ごとなくすには—no-create-infoを付けるといい)

今回は安全に動作(運用)するために付けておくことにする。ここで与えたオプションはlong形式の—add-drop-tableなんだけど、実は引数でtrue falseが与えられるらしい。よくありがちなのは—no-add-drop-tableみたいに対応してる気がしてたんだけどそうじゃないみたい。

公式には書いてないので気がつかなかった。っていうか引数ありって本当意外。

  • --add-drop-table

DROP TABLEステートメントをCREATE TABLEステートメントの前に追加します。
MySQL ::   MySQL 5.1 リファレンスマニュアル :: 7.12 mysqldump — データベースバックアッププログラム

--where=”meta_key!=’views'”

これはmeta_keyで上書きしたくない条件を指定。今回は手元のデータのうち閲覧数は上書きしたくなかった。sqlだったらすんなりwhere句書いちゃえば楽なのになーって思ったらmysqldumpでもwhereが書けるらしい。

  • --where='where_condition', -w 'where_condition'

あるWHERE状態に選択された行のみダンプします。ユーザのコマンドインタープリタにとって特別なキャラクタ、もしくはスペースを含んでいる場合、状態の周りをクオートで囲まなければいけません。

MySQL :: MySQL 5.1 リファレンスマニュアル :: 7.12 mysqldump — データベースバックアッププログラム

–extended-insert=false

キャプチャ2

このオプションも引数を取るらしい。このオプションは

  • --extended-insert, -e

複数のVALUESリストを含む、複数行INSERT構文を使用してください。これにより、ダンプファイルサイズを小さくし、ファイルが再ロードされる際の挿入スピードがあがります。

MySQL :: MySQL 5.1 リファレンスマニュアル :: 7.12 mysqldump — データベースバックアッププログラム

となっている。いわゆるbulk insertとかmultiple-row insertsとか言われてるあれにするようなやつですね。

insert hoge (id, hoge) values (1, hoge), (2, hoge1), (3, hoge), (4, hoge);

で、コレって結構早くする上では重要なものなのです。このオプションがonでないと、bulk insertが有効になっていないと、かなり遅くなります。なのですが後述するmysql -fと組み合わさって今回の運用上はoffにしてないとうまく目的を達成できません。

今回の運用上、というところはどういったところなのか。

さっきの例だとid, hogeという二つのカラムに対して四つの行を一つのinsert文でinsertしようとしてる。で、カラムの名前から分かるように、idというのはpkeyなのでunique制約がある。となるとき、上のinsertだとduplicateでinsertできないことがある。もともとid=1な行があるときとか。で、そういうのは無視しながら必要な行だけをinsertしたいので、これらのinsert文を分けて書く必要がある。なのでこのオプションを有効にしてやる。するとこんな感じのinsert文になる。

insert hoge (id, hoge) values (1, hoge);

insert hoge (id, hoge) values (2, hoge1);

insert hoge (id, hoge) values  (3, hoge);

insert hoge (id, hoge) values (4, hoge);

これでid=1は通らなくても他のinsert文は通ってくれるので期待通りの結果になるかな!

mysql –f

受け側のオプション。エラーがあっても処理を続行する。先のcreate文ですでにtableが存在しても続けたり、insert文でduplicateな行だったとしても続けてくれる。おかげさまでイケるようになります。

おわりに

これでcronに入れとけばテキトウに同期してくれそう。sshでパスワードのプロンプトをなくすために公開鍵をやりとりする、とかやる必要はあるけれど。

でもこれできっと便利。しらばらくは手でやってみるけど。

mysqldumpをやってみた

7.12. mysqldump — データベースバックアッププログラム

mysqldumpを使ったときの

mysqldump –lock-all-tables –master-data=2 –no-create-db –no-create-info –flush-logs –no-autocommit –all-databases > /usr/tmp/dump.sql

–lock-all-tables

すべてのテーブルをロック。リードロック。

–master-data=2

レプリケーションの情報をコメントで書き出してくれる。あとでレプリケーションを再開したいときはmoreとかgrepで中身をみる。1にするとsqlの本文に書かれてしまうらしいのでそれをちょっと抑制するオプション。

–no-create-db

create database文を書かない。

–no-create-info

create table文を書かない。

–flush-logs

ダンプする前にlogの内容をはき出す。

–no-autocommit

テーブルごとにautocommit=0にする。

–all-databases

すべてのデータベースを対象とする。

また有用なオプションについて補足。

たった3秒でInnoDBのデータローディングが快適になるライフハック
–skip-networking

mysqlの起動オプションでネットワークを無効にして立ち上げれるらしい。

  1. mysql> SET sql_log_bin=OFF;
  2. mysql> SOURCE ‘dump.sql’

これでファイルから読み込めるらしい