Wie verhalten sich verteilte Transaktionen mit mehreren Verbindungen zur gleichen Datenbank in einer Thread-Umgebung?

Ich versuche, das Verhalten mehrerer Datenbankverbindungen in einer verteilten Transaktion zu ermitteln.

Ich habe einen lang laufenden Prozess, der eine Reihe von Threads erzeugt, und jeder Thread ist dann für die Verwaltung seiner DB-Verbindungen und dergleichen verantwortlich. All dies läuft innerhalb des Transaktionsbereichs und jeder Thread wird über a in die Transaktion eingetragenDependentTransaction Objekt.

Als ich diesen Prozess parallel startete, stieß ich auf einige Probleme, nämlich dass es anscheinend eine Art Block gab, der die gleichzeitige Ausführung der Abfragen für die Transaktion verhinderte.

Ich möchte wissen, wie der Transaktionskoordinator Abfragen von mehreren Verbindungen zur gleichen Datenbank verarbeitet und ob es überhaupt ratsam ist, ein Verbindungsobjekt über Threads zu übergeben.

Ich habe gelesen, dass MS SQL nur eine Verbindung pro Transaktion zulässt, aber ich bin eindeutig in der Lage, mehr als eine Verbindung zu derselben Datenbank in derselben Transaktion zu erstellen und zu initialisieren. Ich kann die Threads einfach nicht parallel ausführen, ohne beim Öffnen der Verbindungen die Ausnahme "Transaktionskontext wird von einer anderen Sitzung verwendet" zu erhalten. Dies hat zur Folge, dass die Verbindungen warten müssen, bis sie ausgeführt werden, anstatt gleichzeitig ausgeführt zu werden. Am Ende wird der Code vollständig ausgeführt, aber aufgrund dieses Sperrproblems kann das Threading der App nicht fortgesetzt werden.

Der Code sieht ungefähr so aus.

    Sub StartThreads()
        Using Scope As New TransactionScope
            Dim TL(100) As Tasks.Task
            Dim dTx As DependentTransaction
            For i As Int32 = 0 To 100
                Dim A(1) As Object
                dTx = CType(Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete), DependentTransaction)
                'A(0) = some_other_data
                A(1) = dTx 'the Dependent Transaction

                TL(i) = Tasks.Task.Factory.StartNew(AddressOf Me.ProcessData, A) 'Start the thread and add it to the array
            Next

            Tasks.Task.WaitAll(TL) 'Wait for threads to finish

            Scope.Complete()
        End Using
    End Sub
    Dim TransLock As New Object
    Sub ProcessData(ByVal A As Object)
        Dim DTX As DependentTransaction = A(1)
        Dim Trans As Transactions.TransactionScope
        Dim I As Int32
        Do While True
            Try
                SyncLock (TransLock)
                    Trans = New Transactions.TransactionScope(DTX, TimeSpan.FromMinutes(1))
                End SyncLock
                Exit Do
            Catch ex As TransactionAbortedException
                If ex.ToString.Contains("Failure while attempting to promote transaction") Then
                ElseIf ex.Message = "The transaction has aborted." Then
                    Throw New Exception(ex.ToString)
                    Exit Sub
                End If
                I += 1
                If I > 5 Then
                    Throw New Exception(ex.ToString)
                End If
            Catch ex As Exception

            End Try
            Thread.Sleep(10)
        Loop
        Using Trans
            Using DALS As New DAC.DALScope
                Do While True
                    Try
                        SyncLock (TransLock)
                            'This opens two connection to the same DB for later use.
                            DALS.CurrentDAL.OpenConnection(DAC.DAL.ConnectionList.FirstConnection)
                            DALS.CurrentDAL.OpenConnection(DAC.DAL.ConnectionList.SecondConnection)
                        End SyncLock
                        Exit Do
                    Catch ex As Exception
                        'This is usually where I find the bottleneck
                        '"Transaction context in use by another session" is the exception that I get
                        Thread.Sleep(100)
                    End Try
                Loop

                '*****************
                'Do some work here
                '*****************

                Trans.Complete()
            End Using
        End Using
        DTX.Complete()
    End Sub

BEARBEITEN

Meine Tests haben eindeutig gezeigt, dass dies nicht möglich ist. Auch wenn es mehr als eine Verbindung gibt oder dieselbe Verbindung verwendet wird, werden alle Anforderungen in der Transaktion oder die Fragen nacheinander verarbeitet.

Vielleicht werden sie dieses Verhalten in Zukunft ändern.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage