SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

SQL Anywhereの魅力を探る

モバイル環境に分散したデータを同期する「Mobile Link」

SQL Anywhereの魅力を探る 7


  • このエントリーをはてなブックマークに追加

7.1.2 同期プロセス

 これまでのところで、統合データベース、Mobile Linkサーバ、リモートデータベースの役割を説明した。次に、どのように同期処理が行われるのか見ていくことにする。

 同期プロセスは、アップロードとダウンロードの2つのプロセスからなる(図7.7)。同期プロセスの起点は同期クライアントだ(注6)。同期クライアントとは、リモートデータベースと同じデバイス上で動くdbmlsyncというプログラムで、Mobile Linkサーバに対するデータの送受信を担当する。起動された同期クライアントは、リモートデータベースのトランザクションログを調べて、前回同期成功時以降に変更のあった行のみを抽出し、Mobile Linkサーバに送信する(アップロードストリーム)(注7)。送信されるデータの形式はMobile Link独自のものである。

図7.7 : 同期プロセス
図7.7 : 同期プロセス
注6
 では、誰が同期クライアントを実行するのか。基本はデバイス上のユーザ(やアプリケーション)である。定期的に同期をスケジュールすることもできる。また、サーバから指示することもできるが、本稿ではこのサーバ起動同期(Server Initiated Synchronization)に触れないので、詳細についてはマニュアルを参照していただきたい。
注7
 初めての同期であれば、同期設定以降に発生したトランザクションとなる。

 アップロードストリームを受け取ったMobile Linkサーバは、それをSQL文に翻訳して統合データベースにODBC経由で実行する。こうして、リモートデータベースのデータが統合データベースに反映される。翻訳の方法に関しては、あらかじめアップロード用の同期スクリプトとして作成し、統合データベースに保存しておく。Mobile Linkサーバは同期前に同期スクリプトを調べ、同期処理に利用する。

 続いて、Mobile Linkサーバはダウンロード用の同期スクリプトに従って統合データベースからODBCでデータを取得し、そのデータをMobile Link固有のデータ形式にして元の同期クライアントに返信する(ダウンロードストリーム)。この同期スクリプトもSQL文としてあらかじめ用意しておく。

 ダウンロードストリームを受け取った同期クライアントは、そのデータをリモートデータベースに反映させる。

 以上がMobile Linkによる同期プロセスの概略だ。「アップロードとダウンロードの2つの過程で同期が処理され、処理の仕方は同期スクリプトとして作成しておく」ことが現段階ではわかればよいが、ここで重要なポイントは以下の2つだ。

  • Mobile Linkサーバと同期クライアントがトランザクションを管理しているので、同期途中でエラーが起こったり通信回線が切断されてしまったりしても更新データはロールバックされて同期前の状態に戻り、統合データベースもリモートデータベースも不整合を起こさない。
  • 統合データベースから見れば、Mobile LinkサーバはODBC経由でSQLをやり取りする通常のデータベースクライアントなので、同期スクリプトに記述可能なロジックは統合データベースが提供する環境そのものである。よって、同期処理に関する統合データベースの設定やチューニングも、通常のデータベースクライアントと同じように行えばよい。

SQL Anywhere Studio 8からの変更

 SQL Anywhere Studio 8.0.2からは同期プロセスが改良されている。8.0.1までは、ダウンロードストリームのあとでリモートデータベースからMobile Linkサーバへの確認プロセスというものがさらに必要だった。SQL Anywhere Studio 8.0.2以降では、その確認プロセスは省略可能となり、上述したアップロードストリームとダウンロードストリームによる同期プロセスがデフォルトとなっている。確認プロセスがなくなったことで、同期パフォーマンスが向上した。

アップロード時にMobile Linkへ送られるトランザクション

 同期クライアントがリモートデータベースのトランザクションログからアップロードストリームを作成するとき、1つの行(主キー)に対する複数のトランザクションは1つにまとめられ、転送の無駄が省かれる。たとえば、次のようなテーブルがリモートデータベースにあったとしよう。

CREATE TABLE Sample (
    ID       INT PRIMARY KEY,
    VALUE    INT
)

 このテーブルに、3つのトランザクションを流す。

INSERT INTO Sample VALUES (1, 10);
UPDATE Sample SET VALUE = 20 WHERE ID = 1;
UPDATE Sample SET VALUE = 30 WHERE ID = 1;

 ここで同期すると、3つのトランザクションではなく、1つのトランザクションとして送られる。アップロードストリームのイメージを仮にSQL文で表すとすれば、次のようになる。

INSERT INTO Sample VALUES (1, 30)

 このように、1つの行に対してデータ操作を行うSQL文(INSERT、UPDATE、DELETE)を繰り返しても、アップロードストリームでは最終結果となる1つのトランザクションとして送られる(注8)。したがって、追加された行が同期されることなく削除されれば、次回同期時にはその行は送信されない。

注8
 実は最新のデータだけでなく、競合解決用に前回同期成功時の値も送られる。

 以上がデフォルトの動作であるが、同期クライアントの -tuオプションで、この機能をオフにできる(transaction-level upload)。統合データベース側でトリガを利用してロジックを実装しているなど、トランザクションをまとめたくない場合に効果的だ。

アップロードストリームの「前回同期成功時」とは

 アップロードストリーム生成の開始点となる「前回同期成功時」とは、技術的にはトランザクションログのオフセット番号として管理されている(注9)。オフセット番号とは、トランザクションのID番号のことで、コミットごとに採番されてトランザクションログに記録される。オフセット番号の大小はコミットされたトランザクションの時系列に一致し、オフセット番号が小さいほど過去のものとなる。「同期クライアントがアップロードストリームを生成するとき、リモートデータベースのトランザクションログを調べる」と書いたが、これは指定されたオフセット番号以降(から最新まで)のトランザクションについて調べることを意味する。

注9
 progress番号やstate番号と呼ばれることもある。符号なし64ビット整数値なので、値が足りなくなる事態は現実的にはあり得ない。

 前回成功時のオフセット番号は、リモートデータベースのSYSSYNCテーブルと統合データベースのML_SUBSCRIPTIONテーブルが保持し、アップロードストリームの終了時に、新しいオフセット番号がそれぞれ記録される。このためダウンロードストリームの途中で回線が切断して同期が失敗し、再度同期したとしても、すでにオフセット番号は更新されているので(ダウンロードストリームが開始されたということは、アップロードが正常に行われたことを意味する)、先ほどアップロードされたデータが再送される無駄はない。

 アップロードストリーム開始時に統合データベースとリモートデータベースそれぞれのオフセット番号を比較し、データベースの整合性を保とうとする。もし両者のオフセット番号が異なれば、デフォルトでは統合データベースのオフセット番号を使ってアップロードストリームをやり直す。統合データベースのオフセットが小さい場合(統合データベースがバックアップからリストアされた場合など)、アップロード済みのトランザクションが再送される。一方、リモートデータベースのオフセット値が小さい場合(リモートデータベースがバックアップからリストアされた場合など)、統合データベースのオフセット値以降のトランザクションがアップロードされた後データがダウンロードされる。いずれの場合も、障害が起きたほうのデータベースが障害時点のデータに近づくので、通常はこのデフォルト動作で問題ない。

 デフォルト動作で都合が悪い場合は、dbmlsyncの-raや-rbオプションで制御できる。たとえば、バックアップされていたリモートデータベースをリストアした場合、統合データベースのオフセット番号はリストアされたリモートデータベースには存在しない可能性もあり、デフォルト動作では同期できないこともある。このような場合には、-rbオプションを使えばリモートデータベースのオフセット番号が強制的に使われるようになり、同期が成功する。ただし、この場合、同期が成功したとしても、データ抜けが起きえるので、データの一貫性が損なわれる可能性がある。

リモートデータベースのロック

 同期処理の整合性を保つため、同期処理の間(アップロードストリームの作成からダウンロードストリームの適用まで)、同期クライアントはリモートデータベースの同期対象テーブルに共有ロックをかける(注10)。同期処理中に同期とは別のトランザクションが発生してしまうと、前回同期以降の変更をアップロードする際などで整合性が保てないからだ。よって、同期処理中のテーブルに対して、ほかのトランザクションは読み取りできるが書き込みできない。

注10
 Windows CE上の場合は排他ロックとなる。

Mobile Linkサーバのアイソレーションレベル

 Mobile Linkサーバが統合データベースにODBC接続する際、そのアイソレーション(isolation:独立性)レベルはデフォルトでSQL_TXN_READ_COMMITTEDとなっている。競合解決時に反復可能読み取り(repeatable read)が必要となるからだ。

SQL Anywhere 10の場合
 なお、SQL Anywhere 10では、読み取り一貫性が有効であれば、ダウンロードストリームにこれが適用される。
読み取り一貫性を有効にするには(デフォルトは無効)、
SET OPTION PUBLIC.allow_snapshot_isolation = 'On';
とする。

7.1.3 まとめ

 Mobile Linkの同期プロセスはアップロードとダウンロードからなり、統合データベースに保存されているそれぞれの同期スクリプトに従って、Mobile Linkサーバが同期を行う。同期スクリプトの書き方を、次節以降で具体的に見ていく。

次のページ
7.2 Getting Started

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
SQL Anywhereの魅力を探る連載記事一覧

もっと読む

この記事の著者

森脇 大悟(モリワキ ダイゴ)

1974年生まれ。神奈川県川崎市出身。京都大学理学部物理学科卒業。同大学院 修士課程中退後、有限会社グルージェント(現・株式会社グルージェント)入社。SIとして金融や物流システムを手がける。2003年アイエニウェア・ソリューションズ株式会社入社。エンジニアとして製品の導入支援やコンサルティング業務に...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/1749 2008/09/04 13:01

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング