2012-02-29 15 views
7

私はSqlTransactionをC#で実装して、トランザクションのコミットとロールバックを開始しました。すべてがうまくいっていますが、トランザクション中に接続されているテーブルにアクセスしているときに問題があります。 トランザクション中にテーブルを読み取ることができませんでした(これらのテーブルはトランザクション中です)。これについて調べているうちに、排他的ロックが原因で起こることがわかりました。その後、そのデータの後続の選択は、排他ロックが解除されるのを待たなければなりません。その後、私はSqlTransactionによって提供されるすべての分離レベルを通過しましたが、機能しませんでした。 他のユーザーがそのテーブルにアクセスしてデータを読み取れるように、トランザクション中に排他ロックを解除する必要があります。 これを達成する方法はありますか? ありがとうございます。Sqlトランザクションの分離レベル

は、ここでこのコードは正常に動作しているトランザクション

try 
{ 
    SqlTransaction transaction = null;       
    using (SqlConnection connection=new SqlConnection(Connection.ConnectionString)) 
    { 
     connection.Open(); 
     transaction=connection.BeginTransaction(IsolationLevel.Snapshot,"FaresheetTransaction");    
     //Here all transaction occurs 
     if (transaction.Connection != null) 
     {  
       transaction.Commit(); 
       transaction.Dispose(); 
     } 
    } 
} 
catch (Exception ex) 
{ 
    if (transaction.Connection != null) 
     transaction.Rollback(); 
    transaction.Dispose(); 
} `       

のための私のC#のコードだが、問題は、私はトランザクションの期間中テーブルのデータ(トランザクション中にアクセスされたもの)にアクセスするとき。テーブルはアプリケーションの他の部分からアクセスされています。したがって、テーブルからデータを読み込もうとすると、例外がスローされます。

+1

を助けるならば、それはまだ不確実ですので、これは、SQL Server 2008のは、あなたの意図はここで何ですか?更新時にノーロックがかかりませんか?または他の読者がロックを無視するために(非常に良い理由のためにそこにある) –

+1

私は他のユーザーのトランザクションテーブルをロックしたくありません....トランザクションはトランザクションの時に、数十万のデータがテーブルに挿入されるので、おそらく長い時間がかかります...だから、tranの期間私は他のユーザーがそのテーブルにアクセスしてデータを読み取ることができるようにしたい... –

答えて

14

SQLトランザクションは、設計上、ACIDです。特に、ここであなたを傷つけているのは「私」です。これはのように設計されており、他の接続が矛盾した中間状態にならないようにしています。

個々の読み取り接続がNOLOCKヒント、またはREAD UNCOMMITTED分離レベルを使用して、このルールを無視することを選択することができますが、あなたが望むように聞こえるがロックを取らないために書き込み接続のためです。まあ、それは起こらないだろう。

読者は名前が示すように、を見て、(読者がロックを取ることなくアイソレーションを実現しスナップショットアイソレーション、一貫した状態のポイント・イン・タイムshapshotを使用するためしかし、何かもしれないヘルプがありますトランザクションが開始されたとき)。

しかし、IMO方が良いのいずれかを見て賢明でしょう:ステージング表(データの並列コピー)で作業を行う作家

  • から

    • 複数の、よりきめ細かい、取引、その後、いくつかの大量挿入/更新/削除操作でデータにそれをマージするトランザクション時間

    を最小限に最初は簡単です。

    単純な事実は、多くのデータを処理する長時間実行されるトランザクションを実行する場合、はいが原因で問題が発生する可能性があることです。だからあなたはしないでください。システムは正常に動作しています。

  • +2

    2番目のソリューションは、使用されているスナップショットの分離) – ntziolis

    +0

    私はスナップショット分離レベルを使用しましたが、再び同じ問題が発生します....実際には、 "select * from tbl_name(nolock)"を使用すると動作しますが、この選択は私にとっては適切ではありません:1.まだコミットされていないトランザクションのデータを表示しています。 2.テーブルはすでにアプリケーションから照会されているので、コード内のすべてのクエリを調べて変更することはできません。 –

    +1

    @ akash88 **読者**はスナップショットの分離を使用する必要があります。それが助けにならなかったら、あなたは単にスナップショットの分離を有効にしていないのだろうかと思います。しかし、根本的に、あなたはシステムに反することをしようとしています。たとえば、大規模なチャンクを書き直している間に大きなファイルを開いている場合は、読者には進行中の編集が表示されるため共有アクセスを許可したくないのですが、閉じるまでファイルがロックされませんそれをどうやって解決するのですか?答え:あなたはしません。あなたはシステムを異なった方法で設計する。 –

    3

    トランザクション内でも読み取りを実行し、分離レベルREAD UNCOMMITTEDを使用してください。これは、ロックされてからの読み取りを防ぐことができますが、無効な結果が生じる可能性があります:誤解が実際にそれを読んだときも同様に重要であるとき、書き込み時に取引を扱う/分離レベルのみが重要ということがある

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED  
    BEGIN TRANSACTION 
    
    SELECT * FROM Table 
    
    COMMIT TRANSACTION 
    

    +0

    応答ありがとう.....私はすべてのタイプの分離レベルを使用しましたが、それは私のシナリオではうまくいきました。 ..実際には、私はC#でSqlTransactionのBeginTransaction()メソッドを使用しています....私はトランザクションでサスペンドしているそれらのテーブルのための他のユーザーへのアクセスを与えたい.....しかし、すべての分離レベルで排他ロックが発生しています........ –

    +0

    テーブルに書き込む場合、排他ロックは必須です。唯一の例外は、分離レベルのスナップショットを使用する場合ですが、これはsql 2008以降でのみ利用可能であることがわかっている限りです。したがって、読み込みを許可する唯一の方法は、上記で概説した読み込み中に読み込み非コミットまたはカオスの分離レベルを使用することです。 – ntziolis

    +0

    SQL 2005ではスナップショットの分離がすでに利用可能であるため、そこに移動します。作成時にはスナップショットのアイソレーションを使用してください。あなただけが他の操作で読んでいるように見えるので、そこに問題はないはずです。 – ntziolis

    2

    問題は、データベースへの書き込みのレベルではなく、読み取り値のレベルです。挿入している値を読み取ろうとしています。以下に、あなたの選択クエリを変更しよう:

    select * from your_table_with_inserts with (nolock) 
    

    しかし、この1つは現在のトランザクションの分離レベルをオーバーライドし、ダーティリード引き起こす可能性があります。

    質問:すべてのクエリでトランザクションを使用している場合、または挿入/更新のみの場合

    1

    @ AKASH88、SNAPSHOT分離レベルはあなたが探しているものです。

    SNAPSHOTが期待通りに動作しない場合でも、排他ロックが行われていると言いますが、私は同じ問題があることを理解しています。

    データベースオプションでSNAPSHOTを有効にするだけでなく、READ COMMITTED SNAPSHOTを有効にする必要があります。

    enter image description here

    この回答は:(

    よろしく!

    関連する問題