我需要一种可靠的方法,从sql server查询中确定查询是否在分布式事务中运行。
1个
不管分布式事务是在外部创建的还是使用
BEGIN DISTRIBUTED TRANSACTION
声明-不管怎样,我需要知道。
我看不出具体的
SQL Server function
或
stored procedure
声称提供了这些信息。有一些
dynamic-management views
他们的文件声称会提供这些信息,但这些信息是不可靠的。例如,
sys.dm_tran_session_transactions
具有列
is_local
以下内容:
1=本地交易。
0=分布式事务或已登记的绑定会话事务。
所以,测试一下,利用
SAVE TRANSACTION
,其中
is unsupported in a distributed transaction
会导致错误。
2个
此查询不在分布式事务中,并按预期工作,为选择值1
是本地的吗
以下内容:
BEGIN TRANSACTION
SELECT s.is_local
FROM sys.dm_tran_session_transactions s
SAVE TRANSACTION Error
ROLLBACK TRANSACTION
但是,如果我们
BEGIN TRANSACTION
具有
开始分布式事务
我是说,
是本地的吗
仍然是1,但是我们得到错误“不能在分布式事务中使用save事务”。
是本地的吗
价值。
怎么样
sys.dm_tran_active_transactions
是吗?它的
transaction_type
列说明如下:
交易类型。
1=读/写事务
2=只读事务
3=系统事务
4=分布式事务
我们还需要一种方法来识别当前的事务
sys.dm_tran_current_transaction
提供。那么,让我们再次测试一下:
BEGIN TRANSACTION
SELECT a.transaction_type
FROM sys.dm_tran_current_transaction c
INNER JOIN sys.dm_tran_active_transactions a ON c.transaction_id = a.transaction_id
SAVE TRANSACTION Error
ROLLBACK TRANSACTION
对于这个非分布式事务,我们得到一个值1,尽管2也可能是可能的。但是,替换
开始交易
具有
开始分布式事务
同样,我们得到了同样的价值
交易类型
,但这次的错误来自
保存事务
是的。所以,我们不能依赖
交易类型
或者。
为了确保问题不是在分布式事务中实际登记的,我还尝试使用
TransactionScope
来自C代码。
using System;
using System.Data;
using System.Data.SqlClient;
using System.Threading.Tasks;
using System.Transactions;
using IsolationLevel = System.Transactions.IsolationLevel;
namespace TransactionTroubleshooting
{
class Program
{
private const string ConnectionString = "Server=.;Database=master;Trusted_Connection=True;";
// Use C# 7.1 or later.
public static async Task Main(string[] args)
{
try
{
await RunOuterTransaction();
}
catch (Exception e)
{
var current = e;
while (current != null)
{
Console.WriteLine(current.Message);
Console.WriteLine();
Console.WriteLine(current.StackTrace);
Console.WriteLine();
current = current.InnerException;
}
}
finally
{
Console.WriteLine("Press a key...");
Console.ReadKey();
}
}
private static async Task RunOuterTransaction()
{
using (var transaction = new TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions {IsolationLevel = IsolationLevel.ReadCommitted},
TransactionScopeAsyncFlowOption.Enabled))
using (var connection = new SqlConnection(ConnectionString))
{
await connection.OpenAsync();
using (var command = connection.CreateCommand())
{
command.CommandType = CommandType.Text;
command.CommandText = @"
SELECT a.transaction_type
FROM sys.dm_tran_current_transaction c
INNER JOIN sys.dm_tran_active_transactions a ON c.transaction_id = a.transaction_id
";
using (var reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
Console.WriteLine("Outer transaction_type is {0}", reader["transaction_type"]);
}
}
}
await RunInnerTransaction();
transaction.Complete();
}
}
private static async Task RunInnerTransaction()
{
// We need Required, not RequiresNew, to get the distributed transaction.
using (var transaction = new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted },
TransactionScopeAsyncFlowOption.Enabled))
using (var connection = new SqlConnection(ConnectionString))
{
await connection.OpenAsync();
using (var command = connection.CreateCommand())
{
command.CommandType = CommandType.Text;
command.CommandText = @"
SELECT a.transaction_type
FROM sys.dm_tran_current_transaction c
INNER JOIN sys.dm_tran_active_transactions a ON c.transaction_id = a.transaction_id
-- Because this query is in a distributed transaction, if you want to throw, uncomment:
-- SAVE TRANSACTION Error
";
using (var reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
Console.WriteLine("Inner transaction_type is {0}", reader["transaction_type"]);
}
}
}
transaction.Complete();
}
}
}
}
结果:
取消注释
保存事务
做同样的事情,添加一个异常,如预期的,表示一个分布式事务。
是本地的吗
从早期开始也可以进行类似的测试。再一次,也不是
是本地的吗
也不是
交易类型
可靠地表示分布式事务。
我找不到另一种记录在案的方法来尝试在sql中检测分布式事务。有可能吗?如果是,怎么做?
一
这个问题表面上与
.net detect distributed transaction
,但我需要从SQL而不是.NET进行检测。
??
我需要在不引起错误的情况下检测分布式事务,所以不能
保存事务
在我的查询中等待错误。