我正在尝试确定分布式事务中多个数据库连接的行为。
我有一个长时间运行的进程,它产生一系列线程,然后每个线程负责管理其数据库连接等。DependentTransaction
所有这些都在事务范围内运行,并且每个线程都通过一个对象登记在事务中。
当我并行处理这个过程时,我遇到了一些问题,即似乎有某种块阻止查询在事务上同时执行。
我想知道的是事务协调器如何处理来自多个连接到同一个数据库的查询,以及是否建议跨线程传递连接对象?
我读过 MS SQL 每个事务只允许一个连接,但我显然能够在同一个事务中创建和初始化多个到同一个数据库的连接。在打开连接时,如果没有“另一个会话正在使用的事务上下文”异常,我根本无法并行执行线程。结果是连接必须等待执行而不是同时运行,最后代码运行完成,但由于这个锁定问题,线程化应用程序没有净收益。
代码看起来像这样。
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
编辑
我的测试最终表明这是无法做到的。即使有多个连接或使用同一个连接,事务中的所有请求或问题都按顺序处理。
也许他们将来会改变这种行为。