Calendar

November 2010
M T W T F S S
« Oct   Dec »
1234567
891011121314
15161718192021
22232425262728
2930  

データストアをバックアップ、リストア


はじめに

今回は、GAEのデータストアのバックアップ、及び、リストアを試してみます。

きっかけは

この夏からGAEに蓄積しているMETARデータが、無料のDisk Quota(1GB)の 1/3 程度まで成長してきました。
気象データを取得する – GAE編

無料Quotaの上限に達するのはもう少し先ですが、そろそろ古いデータをどうするか考えようと思い、手始めにGAEサーバ上のデータのバックアップ方法を調べてみました。

参考資料

GAEサーバへのデータのアップロード/ダウンロード方法は次のページに書いてあります。(英語です)

参考資料[1] Uploading and Downloading Data

日本語のページが表示される場合、ページ右上で “English” を選ぶか、ブラウザの言語設定で英語を優先させて下さい。

注意:日本語訳のページは古い

邦訳のページはこちらです…

参考資料[2] データのアップロード

2009 年 4 月: Python SDK リリース 1.2.1 には、データのアップロード機能と類似した、データのダウンロード機能の初期バージョンが含まれています。この機能はまだ appcfg.py では使用できませんが、試したい場合は、bulkloader.py をご覧ください。マニュアルを含めたこの機能の完全版を、今後の SDK バージョンでリリース予定です。

*かなり* 古い情報のようです。 現時点(2010/11/2)のSDKは、1.3.8 です。

ページのタイトル「データのアップロード」通り、アップロードの方法しか書いてありませんし、その方法も、英語版では Deprecated(推奨しない)扱いになってます。

バックアップ、リストア手順

Remote API を有効にする

まずは、Remote API を有効にして、アップロード/ダウンロードが出来るようにします。

やり方は簡単です。 app.yaml に次の2行を追加して、アプリを更新するだけです。

(app.yamlに追加する内容)

builtins:
- remote_api: on

追加したら、以下のコマンドでGAEアプリを更新します。

$ python /path/to/appcfg.py update <app-directory>

更新が終わると、次の URL で Remote API にアクセス出来るようになります。

http://<appname>.appspot.com/_ah/remote_api

パスのデフォルト値:/_ah/remote_api は変更可能です。変更方法は、参考資料[1] の “Installing remote_api Using the url Directive” の節を参考にして下さい。

一括バックアップ、リストア

まずは、データストア全体の一括ダウンロード/アップロードについてです。

この方法ではバイナリ形式(SQLite3の内部形式?)のデータでダウンロード/アップロードします。 データベースのダンプを取るのと似ています。

ダウンロード (バックアップ)
全てをダウンロード

(書式)

$ python /path/to/appcfg.py download_data --application=<app-id> \
 --url=http://<appname>.appspot.com/_ah/remote_api \
 --filename=<data-filename>

(注意事項)

  1. –filename で指定したファイルが既に存在するとエラーになります。

  2. SDKの開発用Webサーバでは、全てのエンティティを一括してダウンロードすることは出来ません。

    Note: Downloading all entities of all kinds only works on App Engine, and does not work with the development server.

    開発用Webサーバを使用する場合、次のエンティティ指定でダウンロードを使います。

エンティティ指定でダウンロード

特定のエンティティのみダウンロードする時は、 –kind オプションを指定します。

(書式: エンティティを指定)

$ python /path/to/appcfg.py download_data --application=<app-id>  ---kind=<kind> \
 --url=http://<appname>.appspot.com/_ah/remote_api \
 --filename=<data-filename>
アップロード (リストア)
全てをアップロード

(書式)

$ python /path/to/appcfg.py upload_data --application=<app-id> \
  --filename=<data-filename>  <app-directory>
エンティティ指定でアップロード

特定のエンティティのみアップロードする時は、 –kind オプションを指定します。

(書式: エンティティを指定)

$ python /path/to/appcfg.py upload_data --application=<app-id>  ---kind=<kind> \
  --filename=<data-filename>  <app-directory>

Bulk Loader を使う

上の 一括バックアップ、リストア の方法では、ファイルがバイナリ形式なので、編集するのに不便です。

Bulk Loader を使えば、テキスト形式(CSV, XML)でデータをダウンロード、アップロードが出来るようになります。 例えば、マスターデータをCSVファイルで用意してアップロード、のような操作を行う時はこちらの方法で行います。

bulkloader.yaml を用意する

まずは設定ファイル:bulkloader.yaml を作成します。 既存のアプリから設定ファイルの雛形を自動生成し、生成したファイルに対して修正を加えます。

bulkloader.yaml を生成

生成方法は2種類あります。

(1) ローカルにある開発環境(ソースコード)から生成します。

(書式:アプリケーション開発用ディレクトリを指定)

$ python /path/to/appcfg.py create_bulkloader_config --filename=bulkloader.yaml  \
  <app-directory>

(2) ソースコードがない、または、対象がGAE/Javaアプリの場合、直接、アプリのURLを指定します。

(書式:GAEアプリの Remote API へのURL を指定)

$ python /path/to/appcfg.py create_bulkloader_config --filename=bulkloader.yaml  \
  --url=http://<appname>.appspot.com/_ah/remote_api

(注意事項)

  1. –filename で指定したファイルが既に存在するとエラーになります。

  2. SDKの開発用Webサーバでは設定ファイルを生成出来ません。

    Note: Using the bulk loader to generate a configuration file only works on App Engine, and does not work with the development server.

  3. GAE/Javaアプリがターゲットの場合、Remote API へのパスは変更が必要かもしれません。(未確認です)
bulkloader.yaml を編集

生成した bulkloader.yaml は、そのままでは使えません。 一部を修正する必要があります。(修正が必要な箇所は、ファイル中に # TODO: と書いてあります)

  • connector:

    ファイル形式を選択します。 csv, simplexml, simpletext のいずれかを指定します。

    (例:csv を指定)

    connector: csv
    
  • connector_options:

    オプション指定があれば記述します。なければ、connector_options: の行を削除します。

ダウンロード

bulkloader.yaml が準備出来たら、ダウンロードが出来ます。

(書式)

$ python /path/to/appcfg.py download_data --config_file=bulkloader.yaml  ---kind=<kind> \
 --url=http://<appname>.appspot.com/_ah/remote_api \
 --filename=<data-filename>

(注意事項)

  1. –filename で指定したファイルが既に存在するとエラーになります。

成功すれば、–filename で指定したファイルに、指定の書式でデータが書き出されます。

アップロード

ローカルのファイルをGAEサーバへアップロードも出来ます。

(書式)

$ python /path/to/appcfg.py upload_data --config_file=bulkloader.yaml  ---kind=<kind> \
 --url=http://<appname>.appspot.com/_ah/remote_api \
 --filename=<data-filename>

試してみる

手順は分かったので、実際に試してみます。

Remote API を有効にする

app.yaml に次の2行を追加して、アプリを更新します。

(app.yamlに追加する内容)

builtins:
- remote_api: on

変更後、GAEアプリを更新します。

一括バックアップ、リストア

一括ダウンロード(バックアップ)
$ python /path/to/appcfg.py  download_data --application=<app-id> \
  --url=http://<appname>.appspot.com/_ah/remote_api  \
  --filename=datastore.dump
/path/to/appcfg.py:42: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
  os.path.join(DIR_PATH, 'lib', 'django'),
/path/to/google/appengine/tools/dev_appserver_login.py:33: DeprecationWarning: the md5 module is deprecated; use hashlib instead
  import md5
Downloading data records.
[INFO    ] Logging to bulkloader-log-20101102.105728
[INFO    ] Throttling transfers:
[INFO    ] Bandwidth: 250000 bytes/second
[INFO    ] HTTP connections: 8/second
[INFO    ] Entities inserted/fetched/modified: 20/second
[INFO    ] Batch Size: 10
[INFO    ] Opening database: bulkloader-progress-20101102.105728.sql3
[INFO    ] Opening database: bulkloader-results-20101102.105728.sql3
[INFO    ] Connecting to <appname>.appspot.com/_ah/remote_api
[INFO    ] Downloading kinds: [u'Graph']
.
[INFO    ] Have 2 entities, 0 previously transferred
[INFO    ] 2 entities (45603 bytes) transferred in 3.7 seconds

成功すればローカルに、datastore.dump というファイルが出来ます。

一括アップロード(リストア)

上でダウンロードしたファイルを、今度はアップロードしてみます。

$ python /path/to/appcfg.py  upload_data --application=<app-id> \
  --filename=datastore.dump  <app-directory>

/path/to/appcfg.py:42: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
  os.path.join(DIR_PATH, 'lib', 'django'),
/path/to/google/appengine/tools/dev_appserver_login.py:33: DeprecationWarning: the md5 module is deprecated; use hashlib instead
  import md5
Application: <appname>; version: 1.
Uploading data records.
[INFO    ] Logging to bulkloader-log-20101102.110344
[INFO    ] Throttling transfers:
[INFO    ] Bandwidth: 250000 bytes/second
[INFO    ] HTTP connections: 8/second
[INFO    ] Entities inserted/fetched/modified: 20/second
[INFO    ] Batch Size: 10
[INFO    ] Opening database: bulkloader-progress-20101102.110344.sql3
[INFO    ] Connecting to <appname>.appspot.com/_ah/remote_api
[INFO    ] Starting import; maximum 10 entities per post
.
[INFO    ] 2 entites total, 0 previously transferred
[INFO    ] 2 entities (85305 bytes) transferred in 2.5 seconds
[INFO    ] All entities successfully transferred

(補足)

動作確認の際は、ダウンロードしたアプリとは別のアプリにアップロードしました。
うまくアップロード出来たかの確認は、管理コンソールの Datastore Viewer で行います。

Bulk Loader を使う

まずは、設定ファイル:bulkloader.yaml を用意します。

bulkloader.yaml を生成
$ python /path/to/appcfg.py create_bulkloader_config \
   --filename=bulkloader.yaml   <app-directory>

/path/to/appcfg.py:42: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
  os.path.join(DIR_PATH, 'lib', 'django'),
/path/to/google/appengine/tools/dev_appserver_login.py:33: DeprecationWarning: the md5 module is deprecated; use hashlib instead
  import md5
Application: <appname>; version: 1-1.
Creating bulkloader configuration.
[INFO    ] Logging to bulkloader-log-20101101.144352
[INFO    ] Throttling transfers:
[INFO    ] Bandwidth: 250000 bytes/second
[INFO    ] HTTP connections: 8/second
[INFO    ] Entities inserted/fetched/modified: 20/second
[INFO    ] Batch Size: 10
[INFO    ] Opening database: bulkloader-progress-20101101.144352.sql3
[INFO    ] Opening database: bulkloader-results-20101101.144352.sql3
[INFO    ] Connecting to <appname>.appspot.com/_ah/remote_api
[INFO    ] Downloading kinds: ['__Stat_PropertyType_PropertyName_Kind__']
.[INFO    ] __Stat_PropertyType_PropertyName_Kind__: No descending index on __key__, performing serial download
......
[INFO    ] Have 61 entities, 0 previously transferred
[INFO    ] 61 entities (27632 bytes) transferred in 5.7 seconds

成功すればローカルに、bulkloader.yaml というファイルが出来ます。

bulkloader.yaml を編集

今回は csv 形式で出力するので、connector: に csv を指定します。

(変更前)

  (中略)
- kind: MetarRecord
  connector: # TODO: Choose a connector here: csv, simplexml, etc...
  connector_options:
    # TODO: Add connector options here--these are specific to each connector.
  property_map:
    - property: __key__
      external_name: key
      export_transform: transform.key_id_or_name_as_string
  (中略)

(変更後:csv形式を指定)

- kind: MetarRecord
  connector: csv

  property_map:
    - property: __key__
      external_name: key
      export_transform: transform.key_id_or_name_as_string
ダウンロード

次にGAEアプリからCSVファイル形式でデータをダウンロードします。

$ python  /path/to/appcfg.py  download_data --config_file=bulkloader.yaml \
  --filename=datastore.csv  --kind=<entity_name>  \
  --url=http://<appname>.appspot.com/_ah/remote_api

/path/to/appcfg.py:42: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
  os.path.join(DIR_PATH, 'lib', 'django'),
/path/to/google/appengine/tools/dev_appserver_login.py:33: DeprecationWarning: the md5 module is deprecated; use hashlib instead
  import md5
Downloading data records.
[INFO    ] Logging to bulkloader-log-20101102.102747
[INFO    ] Throttling transfers:
[INFO    ] Bandwidth: 250000 bytes/second
[INFO    ] HTTP connections: 8/second
[INFO    ] Entities inserted/fetched/modified: 20/second
[INFO    ] Batch Size: 10
[INFO    ] Opening database: bulkloader-progress-20101102.102747.sql3
[INFO    ] Opening database: bulkloader-results-20101102.102747.sql3
[INFO    ] Connecting to <appname>.appspot.com/_ah/remote_api
[INFO    ] Downloading kinds: ['<entity_name>']
.[INFO    ] MetarRecord: No descending index on __key__, performing serial download
..........
/path/to/google/appengine/api/datastore_types.py:704: DeprecationWarning: object.__init__() takes no parameters
  super(Link, self).__init__(self, link)
[INFO    ] Have 103 entities, 0 previously transferred
[INFO    ] 103 entities (76552 bytes) transferred in 11.3 seconds

ダウンロードに成功すればローカルに、datastore.csv というファイルが出来ます。

全国の不快指数 – http://99blues.appspot.com/ からダウンロードした結果、次のような CSVファイルが取得出来ました。

wind_speed,code,name,dew_point,wind_compass,discomfort_index,name_jp,longitude,...
5.36448,RJGG,Nagoya Airport,7.0,W,60.107,中部国際空港,136.933,...
4.02336,RJCJ,Chitose Japanese Air Self Defense Force,7.0,NW,48.9007,千歳飛行場,141.683,...
2.2352,RJFE,Fukue Airport,18.0,N,65.8843,五島福江空港,128.833,...

参考までに、ダウンロードしたファイルをこちらに置いておきます。

ダウンロードしたCSVファイル

アップロード

今度は、ダウンロードした CSVファイルを GAEサーバにアップロードします。(動作確認の時は、別のアプリにアップロードしました)

$ python /path/to/appcfg.py  upload_data --config_file=bulkloader.yaml  \
  --filename=MetarRecord.csv  --kind=<entity_name>  \
  --url=http://<appname>.appspot.com/_ah/remote_api

/path/to/appcfg.py:42: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
  os.path.join(DIR_PATH, 'lib', 'django'),
/path/to/google/appengine/tools/dev_appserver_login.py:33: DeprecationWarning: the md5 module is deprecated; use hashlib instead
  import md5
Uploading data records.
[INFO    ] Logging to bulkloader-log-20101101.211230
[INFO    ] Throttling transfers:
[INFO    ] Bandwidth: 250000 bytes/second
[INFO    ] HTTP connections: 8/second
[INFO    ] Entities inserted/fetched/modified: 20/second
[INFO    ] Batch Size: 10
[INFO    ] Opening database: bulkloader-progress-20101101.211230.sql3
[INFO    ] Connecting to <appname>.appspot.com/_ah/remote_api
[INFO    ] Starting import; maximum 10 entities per post
/path/to/google/appengine/api/datastore_types.py:704: DeprecationWarning: object.__init__() takes no parameters
  super(Link, self).__init__(self, link)
...........
[INFO    ] 103 entites total, 0 previously transferred
[INFO    ] 103 entities (182562 bytes) transferred in 13.7 seconds
[INFO    ] All entities successfully transferred

うまくアップロード出来たことを、管理コンソールの Datastore Viewer で確認しました。

最後に

GAEに手を出したのがこの夏(SDK 1.3.5)からだったため、それ以前のSDKの進化を知らずバックアップをどうするのかずっと疑問でしたが、一通りの機能が用意されていて安心しました。 (英語のドキュメントをちゃんと読んでいれば、すぐ分かったことですが…)

まだ、バックアップ・リストアがなんとなく出来るようになっただけで、次のような疑問が残っています。

  1. テキスト形式(CSV,XML)で出力したとき、
    • Blob型はどうなるの?
    • エンティティの親子関係や、参照は保持される?
  2. インデックスは作り直すのかな?
  3. アップロード、ダウンロードに伴う通信量もクォータに計上されるのかな?

まだまだ、いろいろな回避策、ノウハウが必要な気がしますが、この辺はぼちぼち調べていく予定です。

Comments are closed.