2

我读过 Pieter De Rycke 的这篇出色的文章:

http://pieterderycke.wordpress.com/2012/01/22/transactionscope-transaction-escalation-behavior/

我尝试在 Internet 上搜索有关 SQL Server 2012 中事务升级行为的文档,但没有成功。

有谁知道 SQL Server 2012 的行为是否与 SQL2008 不同?我目前在 TransactionScope 和升级到 DTC 方面遇到问题(我不想要)

4

2 回答 2

2

我刚刚尝试了在 SQL Server 2012 (EXPRESS) 中升级到分布式事务的行为。而且我观察到与 SQL Server 2008 相同的行为。

我已经在非常简单的带有SqlConnection对象的代码上对其进行了测试。在一个事务范围内总是有两个数据库访问 (INSERT)。

非嵌套连接 - 未升级

如果您想避免升级为 DTC,这是唯一的选择。在事务期间仅访问一个持久资源(数据库)并在打开另一个连接之前关闭一个连接。(最终,您可以通过重用相同的连接来避免 DT,但是当您使用连接池时没有必要这样做,并且可能会使您的代码可读性降低。)

static string connectionString = "data source=.\\;Integrated Security=SSPI;Database=TestDB";

static void Main(string[] args)
{
    using (var scope = new TransactionScope())
    {
        using (var conn = new SqlConnection(connectionString))
        {
            conn.Open();
            using (var command = conn.CreateCommand())
            {
                command.CommandType = CommandType.Text;
                command.CommandText = "INSERT INTO TestTable(Value) VALUES (@1)";
                command.Parameters.Add(new SqlParameter("1", "123456"));
                command.ExecuteNonQuery();
            }
        }
        using (var conn2 = new SqlConnection(connectionString))
        {
            conn2.Open();
            using (var command2 = conn2.CreateCommand())
            {
                command2.CommandType = CommandType.Text;
                command2.CommandText = "INSERT INTO TestTable(Value) VALUES (@1)";
                command2.Parameters.Add(new SqlParameter("1", "123456"));
                command2.ExecuteNonQuery();
            }
        }
        scope.Complete();
    }
}

嵌套连接 - 升级

static string connectionString = "data source=.\\;Integrated Security=SSPI;Database=TestDB";

static void Main(string[] args)
{
    using (var scope = new TransactionScope())
    {
        using (var conn = new SqlConnection(connectionString))
        {
            conn.Open();
            // EXECUTE INSERT
            using (var conn2 = new SqlConnection(connectionString))
            {
                conn2.Open();
                // EXECUTE INSERT 
            }
        }                
        scope.Complete();
    }
}

访问不同数据库的非嵌套连接 - 升级

如果您在事务期间访问两个或更多持久资源,它将始终被提升为 DTC。

static string connectionString = "data source=.\\;Integrated Security=SSPI;Database=TestDB";
static string connectionString2 = "data source=.\\;Integrated Security=SSPI;Database=TestDB2";

static void Main(string[] args)
{
    using (var scope = new TransactionScope())
    {
        using (var conn = new SqlConnection(connectionString))
        {
            conn.Open();
            // EXECUTE INSERT
        }
        using (var conn2 = new SqlConnection(connectionString2))
        {
            conn2.Open();
            // EXECUTE INSERT 
        }
        scope.Complete();
    }
}

注意 您将执行哪种 CRUD 操作并不重要,它始终取决于打开和关闭连接的方式。

于 2012-12-05T13:18:33.813 回答
1

In @mipe34's third case (different databases on the same server), there's actually a way to prevent DTC escalation by using DbConnection.ChangeDatabase():

static string connectionString = "data source=.\\;Integrated Security=SSPI;Database=TestDB";
static string db2 = "TestDB2";

static void Main(string[] args)
{
    using (var scope = new TransactionScope())
    {
        using (var conn = new SqlConnection(connectionString))
        {
            conn.Open();
            // EXECUTE INSERT
        }
        using (var conn2 = new SqlConnection(connectionString))
        {
            conn2.Open();
            conn2.ChangeDatabase(db2);
            // EXECUTE INSERT 
        }
        scope.Complete();
    }
}

Just make sure that you never Open() a connection, while another one is still open. In that case you will get escalation.

于 2013-10-11T08:18:37.920 回答