C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: 1トランザクションで二つのSQLserverへの処理などを管


(過去ログ 80 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■47187 / inTopicNo.1)  1トランザクションで二つのSQLserverへの処理などを管
  
□投稿者/ iSyouta (1回)-(2010/02/20(Sat) 11:33:13)

分類:[.NET 全般] 

こんにちは。
様々なところで調べたのですがどうしてもわからずこちらに質問させて頂きました。

開発環境:WindowsXP C# .NetFrramework 1.1 SQLServer2005

今、二つの新・旧のSQLサーバーに接続し、同じ内容の更新処理を行うプログラムを作成しております。
同期を取るようなイメージです。

処理の流れとしては旧DBを更新後、新DBを更新するといった感じです。
でここで、
旧DBの更新で失敗した場合は、ロールバックを行い、新DBへの更新処理を行わない
というのはできるのですが、旧DBで更新できて、新DBで更新失敗した場合、新旧ともにロールバック
するという処理を行いたいのですが、どうしてもできません。
SQLサーバーへの接続オブジェクトを別々で作成し、それぞれでBeginTransactionを実行すると
二つ目のBeginTransactionで”sqlClientは並列トランザクションをサポートしていません"
とでます。
これの解決方法もしくは、両方のDBへの処理を1トランザクションで実現できる処理があれば
教えて頂けないでしょうか?
自動トランザクション、分散トランザクションについても調べましたが、実現できるのかも
わかりませんでした。
宜しくお願いいたします。


以下はサンプルです。ところどころ省略してますが、必要な引数等は渡してあります。

try
{
  //旧DBのコネクションオープン
  SqlConnection oldConnct = new SqlConnection(oldConnectionString);
  oldConnct.Open();
  oldConnct.BeginTransaction();

  //新認証DBのコネクションオープン
  SqlConnection newConnct = new SqlConnection(newConnectionString);
  newConnct.Open();
  newConnct..BeginTransaction();←ここでこけます


  //旧認証DB更新SQL実行
  count = SqlHelper.ExecuteNonQuery(oldConnct,CommandType.Text,SqlString,parameterValues);

   //新認証DB更新SQL実行
   count = SqlHelper.ExecuteNonQuery(newConnct,CommandType.Text,SqlString,parameterValues);

   //コミット処理

  }
  catch(Exception ex)
  {
  //ロールバック処理 新DBへの更新が失敗した場合は新旧ともにロールバックを行う。
  throw new Exception(ex.Message);
  }
  finally{
   //コネクションオブジェクトを閉じる。
   oldConnct.Close();
   newConnct.Close();

}


引用返信 編集キー/
■47188 / inTopicNo.2)  Re[1]: 1トランザクションで二つのSQLserverへの処理などを管
□投稿者/ かたぎり (15回)-(2010/02/20(Sat) 13:23:52)
新サーバーへ処理後、
新サーバーのSQLServerからトリガで旧サーバーにデータ処理を行うのはダメですか?

http://msdn.microsoft.com/ja-jp/library/ms178110(SQL.90).aspx

引用返信 編集キー/
■47191 / inTopicNo.3)  Re[2]: 1トランザクションで二つのSQLserverへの処理などを管
□投稿者/ やじゅ (1534回)-(2010/02/20(Sat) 16:28:39)
やじゅ さんの Web サイト
2010/02/22(Mon) 01:52:39 編集(投稿者)

シノニムがSQLServer2005から使えるようになったので、それで出来るんじゃないかな。
新サーバ側に旧サーバのシノニムを作成する。

追記:発想的にはHijunさん同様にリンクサーバ経由のことを想定した回答のつもりでした。
--------------------------------------------------------------------

2相コミットについては、下記サイトが参考になるかも

テーブルアダプタと TransactionScope の組み合わせ
http://blogs.msdn.com/nakama/archive/2008/10/23/transactionscope.aspx

引用返信 編集キー/
■47195 / inTopicNo.4)  Re[3]: 1トランザクションで二つのSQLserverへの処理などを管
□投稿者/ HiJun (140回)-(2010/02/20(Sat) 23:01:02)
リンクサーバ経由でやってみては?

引用返信 編集キー/
■47198 / inTopicNo.5)  Re[1]: 1トランザクションで二つのSQLserverへの処理などを管
□投稿者/ れい (879回)-(2010/02/21(Sun) 01:18:33)
2010/02/21(Sun) 01:21:43 編集(投稿者)

No47187 (iSyouta さん) に返信
> SQLサーバーへの接続オブジェクトを別々で作成し、それぞれでBeginTransactionを実行すると
> 二つ目のBeginTransactionで”sqlClientは並列トランザクションをサポートしていません"
> とでます。
> これの解決方法もしくは、両方のDBへの処理を1トランザクションで実現できる処理があれば
> 教えて頂けないでしょうか?

「両方のDBへの処理を1トランザクションで実現できる処理」が当に「分散Transaction」です。

> どうしてもできません。

とあるように、
2つ以上のサーバーで「原子性」を維持するには
「処理を戻す」もしくは「絶対に更新できることが確認できる」のどちらかが必要で、
それは普通の(サーバー内の)トランザクションを使ってもできません。

分散クエリなど他の手法でもできますが、小さな分散Transactionを行っているのと同様ですので、
件のようなケースでは「分散Transaction」で処理するのが基本であろうと思います。

.Netでは、
SqlConnection.EnlistDistributedTransaction
あたりで分散Transactionを利用できます。
当然、他の手法で「BEGIN DISTRIBUTED TRANSACTION」を発行しても構いません。

ただ、分散Transactionには普通、
クライアント-サーバー間だけではなく、サーバー-サーバー間の通信が必要で、
サーバーがそれができるよう設定されている必要があります。
MSのSQLServerの場合、「MSDTC」が開始していて、きちんと構成されている必要があります。
これが結構めんどくさい。
ファイアーウォールとかRPCとかの問題がいろいろあって。

> 自動トランザクション、分散トランザクションについても調べましたが、実現できるのかも
わかりませんでした。

「分散Transaction」がスタンダードで普遍的であり、確実に実現できる方法です。
より特殊なケースでは他にもいろいろありますが、とりあえずは「分散Transaction」で対応するべきだと思います。

ですが、MSDTCの構成法だとか、分散Transactionの詳細などはとてもここでは説明しきれません。
「分散Transaction」について調べ、わからなければまた質問するとよいかと思います。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -