SQL Server 2012 (EXPRESS) で分散トランザクションへのエスカレーションがどのように動作するかを試しました。また、SQL Server 2008 と同じ動作を確認しました。
オブジェクトを使用した非常に単純なコードでテストしましたSqlConnection
。1 つのトランザクション スコープには、常に 2 つのデータベース アクセス (INSERT) があります。
ネストされていない接続 - エスカレートしない
これは、DTC への昇格を回避したい場合の唯一のオプションです。トランザクション中に 1 つの永続的なリソース (データベース) にのみアクセスし、1 つの接続を閉じてから別の接続を開きます。(最終的には、同じ接続を再利用することで 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();
}
}
異なるデータベースにアクセスするネストされていない接続 - エスカレート中
トランザクション中に 2 つ以上の永続的なリソースにアクセスすると、常に 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 操作の種類は関係ありません。常に、接続がどのように開かれ、閉じられるかによって異なります。