web-dev-qa-db-ja.com

ホストされたデータベースとローカルデータベース間でデータを複製する方法

クラウドでホストされているデータベースを、別の会社が管理しています。これが私のシナリオです:

  • Cloud Hosted Database SQL Server 2012-VPN経由で接続する必要があります。
  • デュアルNICカードでローカルサーバーをセットアップします。これにより、VPN接続とローカルネットワーク接続が可能になります。
  • 私たちのサーバーに、クラウドでホストされているデータベースのローカルコピーが欲しいのですが。
  • SQLサーバー内でレプリケーションをセットアップできません。クラウドサーバーに対する権限がありません。
  • データベースのバックアップと復元を行うことができません-クラウドサーバーに対する権限がありません。
  • トリガーを使用できません
  • ログは使用できません。
  • バックアップは使用できません

データベース、スキーマ、データ全体を停止し、ローカルデータベースをリアルタイムで更新し続けるにはどうすればよいですか?

編集:ホスティング会社からスクリプトを実行して、スキーマと初期データと共にデータベースを作成することができました。

最も重要な質問は、どのようにしてデータをリアルタイムで同期し続けることができるかです。現在、SQLで一連のジョブを実行して、リンクサーバーデータベースに次のようなクエリを実行しようと考えています。

insert into local_table_1
select * from linkedserver_table1
except
select * from local_table_1

問題は、効率が悪く、更新されたレコードをプルしないことです。 「Updated_date」フィールドがあります。ローカルサーバーを更新し、リンクサーバーからすべてのレコードを選択して、ローカルデータベースを更新するにはどうすればよいですか?

4
Shmewnix

特にリモートマシンへのその種のアクセス権がないため、問題に対する複製や標準の解決策はありません。ここの他のコメンターが述べたように、おそらく以下のいずれかの方法で、独自のETLロジックを構築する必要があるでしょう。

  • OPENQUERY()またはOPENROWSET()を使用したリンクサーバーとストアドプロシージャ
  • SSISパッケージ、または
  • カスタムビルドされたローカルアプリケーション。

リモートテーブルの「最終更新」列は、ETLプロセスを実行するたびにデータベース全体のコンテンツをダウンロードする必要がないので、かなり役に立ちます。リモートサーバー上で何かをインストールまたは変更できなければ、「リアルタイム」で同期する実用的な方法はありません。データベースを同期できる頻度と速度は、おそらく次のようになります。

  • リモートデータベースのインデックス作成(新しいレコードを効率的に取得する方法)
  • リモートサーバーのワークロード(ロック、I/O速度、使用可能なCPU)
  • リンク速度(VPNの速度)

1日あたり数回、たとえば、早朝、昼食、午後遅く、および/または夕方にデータを同期するという妥当な期待を設定します。実行計画を立てて、実行中のバックアップジョブ(ローカルで、可能であればリモート)と不必要に衝突しないようにしてください。サーバーに過負荷をかけないように、リモートパーティを関与させます。

T-SQLの例

ストアドプロシージャとリンクサーバーを使用していると仮定すると、これを行う方法についてのアイデアがあります。まず、既存のデータが変更されない場合、つまり行が追加されるだけです(たとえば、会計トランザクションなど)。

DECLARE @lastUpdated   datetime2(3),
        @sql           varchar(max);

--- What's the most recent row we've downloaded?
SELECT @lastUpdated=MAX(lastUpdated)
FROM dbo.tableName;

--- Build dynamic SQL
SET @sql='
    INSERT INTO dbo.tableName (x, y, z, lastUpdated)
    SELECT x, y, z, lastUpdated
    FROM OPENQUERY(linkedServerName, ''
        SELECT x, y, z, lastUpdated
        FROM databaseName.dbo.tableName
        WHERE lastUpdated>={ts '''''+CONVERT(varchar, @lastUpdated, 121)+'''''}
        '');
    ';

--- Execute dynamic SQL
EXECUTE sys.sp_executesql @sql;

...そして、各テーブルに対してこのプロセスを繰り返します。外部キー制約で問題が発生する可能性があるため、テーブルの順序を慎重に調整する必要がある場合がありますが、最終的には、ローカルデータベースに外部キー制約をまったく設定しない方がよい場合があります。

既存の行が変更される可能性がある場合、SQLスクリプトは似ていますが、最初にデータを一時テーブルにダウンロードし、一意のクラスター化された主キーを一時テーブルに割り当て、次に MERGE ( "upsert")一時テーブルの内容をローカルテーブルに。 MERGEが気に入らない、または信頼できない場合は、INSERTおよびUPDATEを従来の方法で使用できます。この方法でリモートテーブルからdeletedされた行をキャッチしないことに注意してください。

SSISの使用

SSISを使用する場合(または独自のローカルアプリケーションを構築する場合)、作業は同じですが、リンクサーバーは必要ありません。sp_executesqlを使用する代わりに、SQLステートメントを動的に構築して実行しますADODBまたは同様のデータベース接続を介して。

完全を期すために「独自のアプリケーションを構築する」オプションを含めました。私はその道を下りません。

インデックス作成に関する考慮事項

リモートクエリを可能な限り効率的にするために、リモートDBAに各テーブルの「最終更新」列にインデックスを設定してもらうことができるかどうかを調査したい場合があります。

バックアップオプション

最後に、おそらくアーロンバートランドの提案を検討して、リモートデータベースのバックアップをダウンロードするソリューション(おそらく1週間に1回はフルバックアップ)をセットアップし、そのバックアップをローカルに復元して、ローカルで同期操作を実行します。サーバ。

リアルタイム

リアルタイムの問題に戻りましょう。ここでの原動力はビジネスでなければなりません。管理がデータベースで最新の精度を必要とする場合、保守は言うまでもなく、誰かが作業とコストの大幅な増加を受け入れる必要があります。最終的に、高速の専用回線の方がはるかに安価で、月に1回程度の巨大なダウンロードでデータをアーカイブできることがわかります。

4