web-dev-qa-db-ja.com

SQL Serverで2つのデータベースを同期する

2つのSQL Serverデータベースがあります。 1つはクライアント(Windowsアプリケーション)で、もう1つはサーバー上にあります。これら2つのデータベースを時々(たとえば、2分ごとに)同期したいと思います。

レプリケーション、タイムスタンプ、トリガーを使用したログテーブル、Microsoft Sync Frameworkなどのさまざまな同期方法について読みました。

実際には、ブラックボックスとなる可能性のある同期方法(レプリケーションなど)を使用したくありません。更新してサーバーと同期しているときにSQL Server固有のテーブルがブロックされないようにするためです。

  1. 私はそのような状況でどの方法を使用すべきだと思いますか?数分おきに、クライアントからサーバーにいくつかのテーブル変更を送信し、サーバーから2つのテーブル変更もフェッチする必要があることに注意してください。

  2. 私は奇妙だが新しい方法を見つけました。クライアントですべての実行された(特定の優先)ストアドプロシージャをログに記録し、.sqlファイルをサーバーに送信し、そこで実行しますか?サーバーでも同じことが起こり、クライアントに送信されます。これはシンプルで便利な方法だと思いますか?

  3. 可能な場合は、役立つアプローチを提案してください。どうもありがとうございます。

編集:これはリアルタイム同期であり、特別なものであることを忘れないでください。つまり、クライアントユーザーがテーブルを使用している場合、サーバーとの同期プロセスは数分おきに行われる必要があるため、ロックされているテーブルはありません。

16
Emad Farrokhi

よくわからないかもしれませんが、答えようとしています。

頻繁に実行される(最低2分すべて)高性能のソリューションが必要であり、ロックせずに高速である適切なアプローチが必要であると述べました。しかし、ブラックボックスシステムは必要ありません。

何百万ものインストールで使用され、優れた結果をもたらすブラックボックスシステムの代わりに、ホイールを再び発明して独自のソリューションを構築しようとしていますか?うーん、少し変に聞こえます。

実際、これらは私の提案です。

  1. レプリケーション使用しないと言ってもこれは、これに使用できる非常に簡単で最適なソリューションです。レプリケーションは簡単にセットアップでき、高速にレプリケーションできます。また、ホイールを発明する必要はありません。ロックがおかしい場合は、ISOLATION LEVELREAD_COMMITTED_SNAPSHOT。あなたはそれについてもっと読むことができます ここ 。これはtempdbの一部を使い果たしますが、テーブルは常に読み取りと書き込みが可能で、レプリケーションはバックグラウンドで機能します。

以下の例をご覧ください。

ALTER DATABASE yourDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE yourDatabase SET READ_COMMITTED_SNAPSHOT ON
  1. [〜#〜] cdc [〜#〜](変更データキャプチャ)も解決策となります。しかし、この方法では、ほぼすべてを自分で構築する必要があります。そして、私はCDCが状況によっては壊れやすいものになる可能性があるという経験をしました。 CDCは、監視対象テーブル上のすべてのデータをキャプチャします(各監視対象テーブルを手動で指定する必要があります)。その後、INSERTUPDATE、またはDELETEの前と後の値を取得します。 CDCは、それらの情報を一定期間保留します(自分で指定できます)。アプローチは、監視する必要がある特定のテーブルでCDCを使用し、それらの変更を他のデータベースに手動で複製することです。ちなみに、CDCは内部でSQL Serverレプリケーションも使用します。 ;-)あなたはそれについてもっと読むことができます ここ

警告:CDCDDL- changesを認識しません。つまり、テーブルを変更して新しい列を追加すると、CDCはテーブルを監視しますが、新しい列に対するすべての変更を無視します。実際、それはNULLを前の値と後の値としてのみ記録します。 DDLの後で再初期化する必要があります_-監視対象テーブルが変更されます。

  1. 上記で説明した方法は、SQL Server Profilerを使用してワークロードをキャプチャし、いくつかのベンチマークのために別のデータベースで再度実行するようなものです。まあそれは働くことができました。しかし、副作用が多すぎるという事実は、私には少し重すぎます。クライアントでプロシージャコールをキャプチャした場合はどうしますか。その後、同期されていないので、主要なデータベースで同じコマンドを実行しますか?プロシージャは実行される可能性がありますが、クライアントに存在しなかった行を削除/更新/挿入する可能性があります。または、1つの原則で複数のクライアントをどのように処理しますか。これはトリッキーすぎると思います。最悪の場合、あなたはおそらくあなたの誠実さを破壊します。
  2. 別のアイデアは、アプリケーションベースまたはトリガーの使用です。同期するテーブルの数によって異なります。すべての変更を個別のステージングテーブルに書き込み、SQL Serverエージェントジョブをすべてx分実行して、ステージングテーブルの行をマスターと同期できます。しかし、たとえば150個のテーブルを同期しようとすると、これは少し重いかもしれません。あなたは大きなオーバーヘッドがあります。

さて、これらは私の2セントです。うまくいけば、あなたは良い概要を持っており、おそらくあなたのために働く1つの解決策を見つけました。

14
Ionic

ここではいくつかのオプションを列挙して、長所と短所を認識します。

  1. SQL Serverレプリケーション -これは、このタスクに最適で最も最適化されたネイティブSQL Serverツールです。ただし、いくつかの問題があります。a。SQL Expressデータベースであるかどうかに関係なく、すべてのクライアントでSQL Server CALライセンスが必要です。これは、プロセッサごとのライセンスを使用することで回避できます。 b。ここで としてSQL CEクライアントを同期することはできません。 c。SQL ExpressまたはLocalDB パブリッシャーまたはディストリビューターとして機能できません なので、レプリケーションプロセスに対するクライアントの制御が弱くなります。
  2. Microsoft Sync Framework-モバイルアプリの小さなデータベースに適しているようです。データベースに非常に多くのテーブルを追加し、レプリケーションほど効率的ではありません。 SQL Serverの外部にコンポーネントとして実装されているため、構成が難しくなります。私はそれを使ったことがなく、試してみて、使わないことにしました。

  3. データベース変更追跡 。これは、挿入、更新、削除などの変更の追跡を行う組み込みのSQL Server関数です。変更の送信と適用、競合の解決など、その他すべては自分でコーディングする必要があります。

  4. Rowversion(timestamp)columnsすべての削除を許可しない場合(削除されたレコードの同期なし)-独自のソリューションベースを実装できます行バージョン情報のみ。 Rowversion列はSQL Serverレプリケーションでも使用されるため、とにかく追加する必要があります。
  5. Ionicの回答に記載されているCDC -これはEnterpriseまたはDeveloperエディションでのみ使用できるため、これに関する経験はありません。

  6. 実行されたストアドプロシージャのログを記録するための独自のトリックの使用-データベースアプリケーションの性質に大きく依存します。しかし、手順がほとんど変わらない場合、データに大きな混乱が生じる可能性があります。そして、どのように紛争に対処しますか?

あなたの質問から、大きなデータベース全体ではなく、いくつかのテーブルだけを同期する必要があるようです。このためには、次のように、質問で指定したよりも詳細にニーズを分析する必要があります。

  • 削除は発生しますか?次に何が発生しますか?
  • 衝突が発生する可能性はありますか?それらをどのように防ぎ、どのように解決するか?
  • テーブル構造の変更をどのように処理しますか?
  • ...

最終的に、削除と競合は問題ではなく、構造はあまり変化しないことがわかった場合は、独自のロジックを作成することを検討できますが、簡単に1000行のコードに拡張できます。

9
Vojtěch Dohnal

フィードバックをありがとうございます。

実行されたストアドプロシージャを束としてではなく1つずつキャプチャすることで、同期プロセスを正常に解決しました。完全性とすべてが慎重に考慮されているため、システムはこれまでリアルタイムで動作しています。

2
Emad Farrokhi

遅い回答ですが、スレッドの訪問者に役立つかもしれません

異なるサーバーにデータを分散しようとする同様の課題があり、サードパーティのツール( Diff スキーマ変更の場合と DataDiff データ変更の同期の場合)とPowerShellスクリプトを使用して解決しましたプロセスを自動化するために必要:

#check for the existence of the Outputs folder
function CheckAndCreateFolder($rootFolder, [switch]$Outputs)
{
$location = $rootFolder

#setting up location 
if($Outputs -eq $true)
{
    $location += "\Outputs"
}

#if the folder doesn't exist it will be created
if(-not (Test-Path $location))
{ mkdir $location -Force:$true -Confirm:$false | Out-Null }

return $location
}

#root folder for the schema sync process
$rootFolder = "SchemaSync"

#schema output summaries location 
$outsLoc = CheckAndCreateFolder $rootFolder -Outputs

#ApexSQL Diff location, date stamp variable is defined, along with tool’s parameters 
$diffLoc   = "ApexSQLDiff"
$stamp = (Get-Date -Format "MMddyyyy_HHMMss") 
$Params = "/pr:""MyProject.axds""    /out:""$outsLoc\SchemaOutput_$stamp.txt"" /sync /v /f" 
$returnCode = $LASTEXITCODE

#initiate the schema comparison and synchronization process
(Invoke-Expression ("& `"" + $diffLoc +"`" " +$Params))

#write output to file
"$outsLoc\SchemaOutput_$dateStamp.txt"

#schema changes are detected
if($returnCode -eq 0)
{
"`r`n $returnCode - Schema changes were successfully synchronized" >> 

}
else
{
#there are no schema changes
if($returnCode -eq 102)
{
"`r`n $returnCode - There are no schema changes. Job aborted" >> 
}
#an error is encountered
else
{
"`r`n $returnCode - An error is encountered" >> 

#output file is opened when an error is encountered
Invoke-Item "$outsLoc\SchemaOutput_$stamp.txt"
}

}

この方法では、2つのデータベース間の比較をスケジュールし、見つかった変更をリアルタイムで同期します。ステップバイステップの説明を提供するいくつかの記事はここにあります:

https://solutioncenter.apexsql.com/automatically-compare-and-synchronize-sql-server-data/https://solutioncenter.apexsql.com/how-to-automatically -keep-two-sql-server-database-schemas-in-sync /

0
Monte Chavis