おぎわらさんの記事
[記事リンク]【超重要】データベースミラーリング (DBM) 利用時のアプリケーション設計・実装の注意点(PDF)
を読ませていただいて、ざっとだけ(自分に関係しそうな所だけ^^;)PDF読んでみました。
忘れない為にメモしとこう
■同期を取る為に、内部で下記動作を行っている
1. ログ情報の転送(プリンシパル -> ミラー)
2. ログ情報の反映(ミラー -> プリンシパル)
■DBM仕様による制限事項をうけないアプリケーション構成は下記
1. ローカルトランザクションである
(単一のSQLServer2005インスタンスに対してのみ処理を行う)
2. 単一データベース内のテーブル郡のみを処理する
3. マニュアルトランザクション(DBトランザクション含む)である
上記の構成以外であれば、
DBMフェイルオーバー時に原子性の破損、
AP/DBで不整合が発生する可能性がある
■ローカル型DTCトランザクションの注意
~TransactionScope + TableAdapterの組み合わせパターンで開発する場合~
○上記パターンでの開発時、
アプリとDBの間で「アプリ側はコミット完了、DB側はロールバック」という
不整合が発生する可能性がある。
※DB間の不整合は発生しない
○不整合が発生するシーケンス
a)MS-DTCがコミットを決定、
SQLServerに"非同期"でコミット要求を発行し、
アプリにはコミット応答を返す
b)直後にSQLServer側で障害が発生し、
DBMファイルオーバーが発生すると、
DB側のトランザクションはロールバックされる
○コードの例
using (TransactionScope scope =
new TransactionScope(TransactionScopeOption.RequiresNew))
{
TableAdapter.GetData(); ・・・※1
~処理~
TableAdapter.Update(); ・・・※2
scope.Complete();
}
※1と※2ではTableAdapterにより自動的に
ConnectionのOpen/Closeが行われる為、
Connectionが異なりMS-DTCが利用される
○回避作
a)コネクション変更によるLCTの利用(コード変更要)
・MS-DTCにならないようにする方法
・上記コード例を変更すると下記のようにする
using (TransactionScope scope =
new TransactionScope(TransactionScopeOption.RequiresNew))
{
try
{
TableAdapter.Connection.Open(); ・・・※1
TableAdapter.GetData();
~処理~
TableAdapter.Update();
}
finally
{
TableAdapter.Connection.Close();
}
scope.Complete();
}
※1 事前にConnectionを開いて置く事により、
TableAdapter内でのConnectionOpen操作を抑制し、
MS-DTCを利用しないようにする。
(MS-DTCは、下記条件であれば利用されない)
・利用するデータベースサービスが単一
・スコープ内で単一の接続しか利用されない
・スコープ内で単一の接続のOpen/Closeを繰り返しても駄目
b)ServiceDomainの利用によるSPC最適化(コード変更要)
c)セントラルMS-DTCサーバーによるSPC最適化
d)(非回避策)アプリケーションログによる運用対処
やばい・・・今のプロジェクトTableAdapterの自動Open/Closeとか使ってるような気がする・・・
しかもミラーリングも使ってる・・・
-- 11/01 15:00 追記 --
フレームワーク開発担当の方に聞くと、
MS-DTCへ昇格しないようにしているとの事。
さすがです(´▽`)