4

私は次のルーチンを持っています:

For j = 1 To NumItems
    dbValueLookup.Load(j)
    Using scope As New TransactionScope()
        For i = firstIndex To lastIndex

            'dbValueLookup is basically just a Dictionary of items already in the DB
            If dbValueLookup.ContainsKey(i) Then
                'updateData is a subroutine that updates this row with new data
                updateData(j,i)
                rowsUpdated = rowsUpdated + 1
                dbValueLookup.Remove(i)
            Else
                'updateData is a subroutine that adds a new row to DB
                addData(j,i)
                rowsAdded = rowsAdded + 1
            End If
        Next

        If dbValueLookup.Count = 0 Then
            'This commits the transaction - records will be updated when End Using is reached
            scope.Complete()
            If rowsAdded + rowsUpdated > 0 Then
                ShowMessage("Records Updated: " + rowsUpdated.ToString() + " Records Added: " + rowsAdded.ToString())
            End If

        Else
            'We are left with data from the database that was not updated.  This is a problem, so we don't "Complete" the scope.
            'This will result in a rollback.
            ShowWarningMessage("Incomplete Data for " + i.ToString())
        End If
    End Using
Next

これを本番環境とテスト環境の両方の Oracle 11g データベースに対して散発的に実行すると (または、パターンがある場合は、まだ見つかっていません)、Oracle エラーが生成されます: ORA-02049: タイムアウト: 分散トランザクションがロックを待機しています。

これはテスト データベースに対して実行される唯一のプロセスであるため、さまざまなユーザーがロックをめぐって競合するという問題は発生しません。

このエラーの原因は何ですか?

前もって感謝します。

4

1 に答える 1

0

したがって、行ロックをめぐって 2 つのトランザクションが競合する必要があるように思えます。

ここでブレインストーミングを行いますが、 の場合dbValueLookup.Count = 0addData(? のように聞こえます) を呼び出しますが、トランザクションをコミットするためにINSERT呼び出すことはありません。scope.Complete()

End Usingが常にトランザクションをコミットするかどうかはわかりません。

TransactionScopeループの反復ごとに を本当に作成する必要がありますか? 1 つのトランザクションを作成し、すべての更新/挿入を行ってから、一度コミットしてみませんか?

于 2011-06-26T00:09:30.643 に答える