이 문서는 기계 번역을 이용하여 번역되었습니다. 문서를 영문으로 보려면 영문 확인란을 선택하세요. 마우스 포인터를 텍스트 위로 이동시켜 팝업 창에서 영문 텍스트를 표시할 수도 있습니다.
번역
영문

IsolationLevel 열거형

 

게시 날짜: 2016년 11월

연결에 대한 트랜잭션 잠금 동작을 지정합니다.

네임스페이스:   System.Data
어셈블리:  System.Data(System.Data.dll에 있음)

public enum IsolationLevel

멤버 이름설명
Chaos

격리 수준이 높은 트랜잭션에서 보류 중인 변경 내용은 덮어쓸 수 없습니다.

ReadCommitted

공유 잠금은 더티 읽기를 방지 하는 데이터를 읽는 동안 반복 불가능 읽기 나 팬텀 데이터가 생성 하는 트랜잭션 종료 되기 전에 데이터를 변경할 수 있습니다.

ReadUncommitted

커밋되지 않은 읽기 불가능 즉 없는 공유 잠금이 실행 되 고 없는 배타적 잠금이 유지 되지 않습니다.

RepeatableRead

다른 사용자 데이터를 업데이트 하는 것을 방지 하는 쿼리에 사용 되는 모든 데이터에 잠금은 배치 됩니다. 반복 불가능 읽기 하지만 팬텀 방지 행은 여전히 가능 합니다.

Serializable

에 범위 잠금이 적용 됩니다는 DataSet, 다른 사용자는 트랜잭션이 완료 될 때까지 데이터 집합에 행을 삽입 하거나 업데이트할 수 없게 합니다.

Snapshot

한 응용 프로그램은 동일한 데이터를 수정 하는 다른 하는 동안 읽을 수 있는 데이터의 버전을 저장 하 여 차단을 줄입니다. 한 트랜잭션에서 확인할 수 없는 다른 트랜잭션의 변경 내용을 다시 쿼리 해도 나타냅니다.

Unspecified

사용 되는 지정 된 것 보다 다른 격리 수준을 있지만 수준을 확인할 수 없습니다.

IsolationLevel 값 트랜잭션을 수행 하는 경우.NET Framework 데이터 공급자가 사용 됩니다.

IsolationLevel 계속 적용 될 때까지 명시적으로 변경 되지만 언제 든 지 변경할 수 있습니다. 새 값은 구문 분석 시간이 아닌 실행 시 사용 됩니다. 트랜잭션 중 변경 하는 경우 예상 되는 동작은 서버 나머지 모든 문에 새 잠금 수준을 적용 하는 합니다.

이 응용 프로그램을 사용 하는 방법을 보여 줍니다 IsolationLevel 에서 DbTransaction합니다. 샘플에서는 다른 격리 수준에서 허용 되는 다음 동작 중 보여 줍니다.

  • 더티 읽기입니다.

  • 반복 불가능 읽습니다.

  • 팬텀 합니다.

이 응용 프로그램은 다음 격리 수준에서 실행 합니다.

  • ReadUncommitted

  • ReadCommitted

  • RepeatableRead

  • 직렬화 가능

  • 스냅숏

PhantomReadThreads 클래스 특정 트랜잭션이 팬텀 읽기 동작을 허용 하는 방법을 보여 줍니다. 트랜잭션 동작을 허용 하는 경우 스레드는 다음 순서 운영 됩니다.

  • 첫 번째 스레드는 products(All)를 선택 합니다.

  • 두 번째 스레드는 새 제품을 삽입 합니다.

  • 두 번째 스레드에서 트랜잭션을 커밋하십시오.

  • 제품을 다시 선택 합니다.

  • 첫 번째 스레드가에서 트랜잭션을 커밋하십시오.

트랜잭션 동작을 허용 하는 경우 두 개의 Select 작업 다른 결과 얻을 수 있습니다.

NonrepeatableReadThreads 클래스 경우 특정 트랜잭션을 통해 반복 되지 않는 읽기 동작 하는 방법을 보여 줍니다. 트랜잭션 동작을 허용 하는 경우 스레드는 다음 순서 운영 됩니다.

  • 첫 번째 스레드는 product(ProductId=1)를 선택 합니다.

  • 두 번째 스레드에서 수량 value(ProductId=1)를 업데이트 합니다.

  • 두 번째 스레드에서 트랜잭션을 커밋하십시오.

  • 제품을 다시 선택 합니다.

  • 첫 번째 스레드가에서 트랜잭션을 커밋하십시오.

트랜잭션 동작을 허용 하는 경우 두 개의 Select 작업 다른 결과 얻을 수 있습니다.

ExchangeValuesThreads 클래스 Serializable 및 스냅숏 트랜잭션 간의 차이 보여 줍니다. 에 직렬화 가능 트랜잭션 스레드는 다음 순서 대로 작동 합니다.

  • 첫 번째 스레드에서 변수에 product(ProductId=2)와 저장소의 가격을 가져옵니다.

  • 첫 번째 스레드에서 product(ProductId=2)의 가격으로 product(ProductId=1)의 가격을 업데이트 합니다.

  • 첫 번째 스레드가에서 트랜잭션을 커밋하십시오.

  • 두 번째 스레드에서 변수에 product(ProductId=1)와 저장소의 가격을 가져옵니다.

  • 두 번째 스레드에서 product(ProductId=1)의 가격으로 product(ProductId=2)의 가격을 업데이트 합니다.

  • 두 번째 스레드에서 트랜잭션을 커밋하십시오.

이제 가격의 값 (ProductId = 1 및 ProductId = 2)는 원래 Product(ProductId=2) 가격와 동일 합니다.

스냅숏 트랜잭션에 대 한 스레드는 다음 순서 운영 됩니다.

  • 첫 번째 스레드에서 변수에; product(ProductId=2)와 저장소의 가격을 가져옵니다

  • 첫 번째 스레드에서 product(ProductId=2)의 가격으로 product(ProductId=1)의 가격을 업데이트 합니다.

  • 두 번째 스레드에서 스냅숏에서 product(ProductId=1)의 가격을 가져와 변수에 저장 합니다.

  • 두 번째 스레드에서 product(ProductId=1)의 가격으로 product(ProductId=2)의 가격을 업데이트 합니다.

  • 두 번째 스레드에서 트랜잭션을 커밋하십시오.

  • 첫 번째 스레드가에서 트랜잭션을 커밋하십시오.

이제 제품의 가격을 교환 (ProductId = 1 및 ProductId = 2).

DirtyReadThreads 클래스 특정 트랜잭션이 커밋되지 않은 읽기 동작을 허용 하는 방법을 보여 줍니다. 트랜잭션 동작을 허용 하는 경우 스레드는 다음 순서 운영 됩니다.

  • 첫 번째 스레드가에서 트랜잭션을 시작 하 고 수량 value(ProductId=1)를 추가 합니다.

  • 두 번째 스레드에서 수량 값을 읽고 값을 다시 추가 합니다.

  • 두 번째 스레드에서 트랜잭션을 커밋하십시오.

  • 첫 번째 스레드가에서 트랜잭션을 롤백하십시오.

트랜잭션 동작을 허용 하는 경우에 수량 값을 두 번 추가 됩니다.

이 코드 예제와 함께 C# 및 Visual Basic 프로젝트에서 찾을 수 있습니다 Developer Code Samples합니다.

using System;
using System.Data.SqlClient;
using System.Data;
using System.Threading;
using System.Threading.Tasks;

namespace CSDataIsolationLevel {

   // Use the delegate to call the different threads.
   public delegate void AsyncAccessDatabase(String connString, IsolationLevel level);

   static class DirtyReadThreads {
      public static void DirtyReadFirstThread(String connStrig, IsolationLevel level) {
         Console.WriteLine("Begin the DirtyReadFirstThread.....");

         using (SqlConnection conn = new SqlConnection(connStrig)) {
            String cmdText = @"Use DbDataIsolationLevel; 

                    Update dbo.Products set Quantity=Quantity+100 where ProductId=1;
                    WaitFor Delay '00:00:06';";

            conn.Open();

            using (SqlTransaction tran = conn.BeginTransaction(level, "DirtyReadFirst")) {
               using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                  command.Transaction = tran;
                  command.ExecuteNonQuery();
               }

               if (tran != null)
                  tran.Rollback();
            }
         }

         Console.WriteLine("Exit from the DirtyReadFirstThread.....");
      }

      public static void DirtyReadSecondThread(String connStrig, IsolationLevel level) {
         Console.WriteLine("Begin the DirtyReadSecondThread.....");

         using (SqlConnection conn = new SqlConnection(connStrig)) {
            String cmdText = @"Use DbDataIsolationLevel;

                    WaitFor Delay '00:00:03'; 

                    Declare @qty int;
                    select @qty=Quantity from dbo.Products where ProductId=1;

                    Update dbo.Products set Quantity=@qty+100 where ProductId=1;";

            conn.Open();

            using (SqlTransaction tran = conn.BeginTransaction(level, "DirtyReadSecond")) {
               using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                  command.Transaction = tran;
                  command.ExecuteNonQuery();
               }
               tran.Commit();
            }
         }

         Console.WriteLine("Exit from the DirtyReadSecondThread.....");
      }
   }


   static class NonrepeatableReadThreads {
      public static void NonrepeatableReadFirstThread(String connStrig, IsolationLevel level) {
         Console.WriteLine("Begin the NonrepeatableReadFirstThread.....");

         using (SqlConnection conn = new SqlConnection(connStrig)) {
            String cmdText = @"Use DbDataIsolationLevel; 

                    Select ProductId,ProductName,Quantity,Price
                    from dbo.Products
                    where ProductId=1

                    WaitFor Delay '00:00:06';

                    Select ProductId,ProductName,Quantity,Price
                    from dbo.Products
                    where ProductId=1";

            conn.Open();

            using (SqlTransaction tran = conn.BeginTransaction(level, "NonrepeatableReadFirst")) {
               using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                  command.Transaction = tran;

                  using (SqlDataReader reader = command.ExecuteReader()) {
                     Boolean isFirstReader = true;
                     do {
                        Console.WriteLine("It's the result of {0} read:", isFirstReader ? "first" : "second");
                        TransactionIsolationLevels.DisplayData(reader);
                        isFirstReader = !isFirstReader;
                     } while (reader.NextResult() && !isFirstReader);
                  }
               }

               tran.Commit();
            }
         }

         Console.WriteLine("Exit from the NonrepeatableReadFirstThread.....");
      }

      public static void NonrepeatableReadSecondThread(String connStrig, IsolationLevel level) {
         Console.WriteLine("Begin the NonrepeatableReadSecondThread.....");

         using (SqlConnection conn = new SqlConnection(connStrig)) {
            String cmdText = @"Use DbDataIsolationLevel;

                    WaitFor Delay '00:00:03'; 

                    Update dbo.Products set Quantity=Quantity+100 where ProductId=1;";

            conn.Open();

            using (SqlTransaction tran = conn.BeginTransaction(level, "NonrepeatableReadSecond")) {
               using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                  command.Transaction = tran;
                  command.ExecuteNonQuery();
               }
               tran.Commit();
            }
         }

         Console.WriteLine("Exit from the NonrepeatableReadSecondThread.....");
      }
   }


   static class PhantomReadThreads {
      public static void PhantomReadFirstThread(String connStrig, IsolationLevel level) {
         Console.WriteLine("Begin the PhantomReadFirstThread.....");

         using (SqlConnection conn = new SqlConnection(connStrig)) {
            String cmdText = @"Use DbDataIsolationLevel; 

                    Select ProductId,ProductName,Quantity,Price
                    from dbo.Products

                    WaitFor Delay '00:00:06';

                    Select ProductId,ProductName,Quantity,Price
                    from dbo.Products";

            conn.Open();

            using (SqlTransaction tran = conn.BeginTransaction(level, "PhantomReadFirst")) {
               using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                  command.Transaction = tran;

                  using (SqlDataReader reader = command.ExecuteReader()) {
                     Boolean isFirstReader = true;
                     do {
                        Console.WriteLine("It's the result of {0} read:", isFirstReader ? "first" : "second");

                        TransactionIsolationLevels.DisplayData(reader);

                        isFirstReader = !isFirstReader;
                     } while (reader.NextResult() && !isFirstReader);
                  }
               }

               tran.Commit();
            }
         }
         Console.WriteLine("Exit from the PhantomReadFirstThread.....");
      }

      public static void PhantomReadSecondThread(String connStrig, IsolationLevel level) {
         Console.WriteLine("Begin the PhantomReadSecondThread.....");

         using (SqlConnection conn = new SqlConnection(connStrig)) {
            String cmdText = @"Use DbDataIsolationLevel;

                    WaitFor Delay '00:00:03'; 

                    INSERT [dbo].[Products] ([ProductName], [Quantity], [Price]) 
                    VALUES (N'White Bike', 843, 1349.00)";

            conn.Open();

            using (SqlTransaction tran = conn.BeginTransaction(level, "PhantomReadSecond")) {
               using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                  command.Transaction = tran;
                  command.ExecuteNonQuery();
               }
               tran.Commit();
            }
         }

         Console.WriteLine("Exit from the PhantomReadSecondThread.....");
      }
   }


   // Demonstrates if the specific transaction allows the following behaviors:
   // 1. Dirty reads;
   // 2. Non-repeatable reads;
   // 3. Phantoms.
   static class TransactionIsolationLevels {
      public static void DemonstrateIsolationLevel(String connString, IsolationLevel level) {
         // Before connect the database, recreate the table.
         OperateDatabase.CreateTable(connString);
         DemonstrateIsolationLevel(connString, level, DirtyReadThreads.DirtyReadFirstThread, DirtyReadThreads.DirtyReadSecondThread);
         DisplayData(connString);
         Console.WriteLine();

         OperateDatabase.CreateTable(connString);
         DemonstrateIsolationLevel(connString, level, NonrepeatableReadThreads.NonrepeatableReadFirstThread, NonrepeatableReadThreads.NonrepeatableReadSecondThread);
         Console.WriteLine();

         OperateDatabase.CreateTable(connString);
         DemonstrateIsolationLevel(connString, level, PhantomReadThreads.PhantomReadFirstThread, PhantomReadThreads.PhantomReadSecondThread);
         Console.WriteLine();
      }

      // Demonstrates if the specific transaction allows the specific behaviors.
      public static void DemonstrateIsolationLevel(String connString, IsolationLevel level,
          AsyncAccessDatabase firstThread, AsyncAccessDatabase secondThread) {
         Task[] tasks ={
                            Task.Factory.StartNew(()=>firstThread(connString, level)),
                            Task.Factory.StartNew(()=>secondThread(connString, level))
                        };

         Task.WaitAll(tasks);
      }

      static class ExchangeValuesThreads {
         public static void ExchangeValuesFirstThread(String connStrig, IsolationLevel level) {
            Console.WriteLine("Begin the ExchangeValuesFirstThread.....");

            using (SqlConnection conn = new SqlConnection(connStrig)) {
               String cmdText = @"Use DbDataIsolationLevel;

                    Declare @price money;
                    select @price=Price from dbo.Products where ProductId=2;

                    Update dbo.Products set Price=@price where ProductId=1;

                    WaitFor Delay '00:00:06'; ";

               conn.Open();
               using (SqlTransaction tran = conn.BeginTransaction(level, "ExchangeValuesFirst")) {

                  using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                     command.Transaction = tran;
                     command.ExecuteNonQuery();
                  }

                  tran.Commit();
               }
            }

            Console.WriteLine("Exit from the ExchangeValuesFirstThread.....");
         }

         public static void ExchangeValuesSecondThread(String connStrig, IsolationLevel level) {
            Console.WriteLine("Begin the ExchangeValuesSecondThread.....");

            using (SqlConnection conn = new SqlConnection(connStrig)) {
               String cmdText = @"Use DbDataIsolationLevel;

                    WaitFor Delay '00:00:03'; 

                    Declare @price money;
                    select @price=Price from dbo.Products where ProductId=1;

                    Update dbo.Products set Price=@price where ProductId=2;";

               conn.Open();

               using (SqlTransaction tran = conn.BeginTransaction(level, "ExchangeValuesSecond")) {
                  using (SqlCommand command = new SqlCommand(cmdText, conn)) {
                     command.Transaction = tran;
                     command.ExecuteNonQuery();
                  }
                  tran.Commit();
               }
            }

            Console.WriteLine("Exit from the ExchangeValuesSecondThread.....");
         }
      }

      // Demonstrates the difference between the Serializable and Snapshot transaction
      public static void DemonstrateBetweenSnapshotAndSerializable(String connString) {
         OperateDatabase.CreateTable(connString);

         Console.WriteLine("Exchange Vaules in the Snapshot transaction:");
         DemonstrateIsolationLevel(connString, IsolationLevel.Snapshot,
             ExchangeValuesThreads.ExchangeValuesFirstThread,
             ExchangeValuesThreads.ExchangeValuesSecondThread);
         DisplayData(connString);
         Console.WriteLine();

         Console.WriteLine("Cannot Exchange Vaules in the Serializable transaction:");
         OperateDatabase.CreateTable(connString);
         DemonstrateIsolationLevel(connString, IsolationLevel.Serializable,
             ExchangeValuesThreads.ExchangeValuesFirstThread,
             ExchangeValuesThreads.ExchangeValuesSecondThread);
         DisplayData(connString);
      }

      public static void DisplayData(String connString) {
         using (SqlConnection conn = new SqlConnection(connString)) {
            String cmdText = @"Use DbDataIsolationLevel; 

                    Select ProductId,ProductName,Quantity,Price
                    from dbo.Products";

            conn.Open();

            using (SqlCommand command = new SqlCommand(cmdText, conn)) {
               using (SqlDataReader reader = command.ExecuteReader()) {
                  DisplayData(reader);
               }
            }
         }
      }

      public static void DisplayData(SqlDataReader reader) {
         Boolean isFirst = true;

         while (reader.Read()) {
            if (isFirst) {
               isFirst = false;

               for (int i = 0; i < reader.FieldCount; i++)
                  Console.Write("{0,-12}   ", reader.GetName(i));
               Console.WriteLine();
            }

            for (int i = 0; i < reader.FieldCount; i++)
               Console.Write("{0,-12}   ", reader[i]);
            Console.WriteLine();
         }
      }
   }

   // This class includes database operations. If there's no database 'DbDataIsolationLevel', create the database.
   static class OperateDatabase {
      public static Boolean CreateDatabase(String connString) {
         using (SqlConnection conn = new SqlConnection(connString)) {
            String cmdText = @"Use Master;

                                     if Db_Id('DbDataIsolationLevel') is null
                                      create Database [DbDataIsolationLevel];";

            using (SqlCommand command = new SqlCommand(cmdText, conn)) {
               conn.Open();
               command.ExecuteNonQuery();
            }

            Console.WriteLine("Create the Database 'DbDataIsolationLevel'");
         }

         return true;
      }


      // If there's no table [dbo].[Products] in DbDataIsolationLevel, create the table; or recreate it.
      public static Boolean CreateTable(String connString) {
         using (SqlConnection conn = new SqlConnection(connString)) {
            String cmdText = @"Use DbDataIsolationLevel

                                    if Object_ID('[dbo].[Products]') is not null
                                    drop table [dbo].[Products]

                                    Create Table [dbo].[Products]
                                    (
                                    [ProductId] int IDENTITY(1,1) primary key,
                                    [ProductName] NVarchar(100) not null,
                                    [Quantity] int null,
                                    [Price] money null
                                    )";

            using (SqlCommand command = new SqlCommand(cmdText, conn)) {
               conn.Open();
               command.ExecuteNonQuery();
            }
         }

         return InsertRows(connString);
      }

      // Insert some rows into [dbo].[Products] table.
      public static Boolean InsertRows(String connString) {
         using (SqlConnection conn = new SqlConnection(connString)) {
            String cmdText = @"Use DbDataIsolationLevel

                    INSERT [dbo].[Products] ([ProductName], [Quantity], [Price]) VALUES (N'Blue Bike', 365,1075.00)
                    INSERT [dbo].[Products] ([ProductName], [Quantity], [Price]) VALUES (N'Red Bike', 159, 1299.00)
                    INSERT [dbo].[Products] ([ProductName], [Quantity], [Price]) VALUES (N'Black Bike', 638, 1159.00)";

            using (SqlCommand command = new SqlCommand(cmdText, conn)) {
               conn.Open();
               command.ExecuteNonQuery();
            }
         }
         return true;
      }

      // Turn on or off 'ALLOW_SNAPSHOT_ISOLATION'
      public static Boolean SetSnapshot(String connString, Boolean isOpen) {
         using (SqlConnection conn = new SqlConnection(connString)) {
            String cmdText = null;

            if (isOpen)
               cmdText = @"ALTER DATABASE DbDataIsolationLevel SET ALLOW_SNAPSHOT_ISOLATION ON";
            else
               cmdText = @"ALTER DATABASE DbDataIsolationLevel SET ALLOW_SNAPSHOT_ISOLATION OFF";

            using (SqlCommand command = new SqlCommand(cmdText, conn)) {
               conn.Open();
               command.ExecuteNonQuery();
            }
         }

         return true;
      }
   }
   class Program {
      static void Main(string[] args) {
         String connString = "Data Source=(local);Initial Catalog=master;Integrated Security=True;Asynchronous Processing=true;";

         OperateDatabase.CreateDatabase(connString);
         Console.WriteLine();

         Console.WriteLine("Demonstrate the ReadUncommitted transaction: ");
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString,
             System.Data.IsolationLevel.ReadUncommitted);
         Console.WriteLine("-----------------------------------------------");

         Console.WriteLine("Demonstrate the ReadCommitted transaction: ");
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString,
             System.Data.IsolationLevel.ReadCommitted);
         Console.WriteLine("-----------------------------------------------");

         Console.WriteLine("Demonstrate the RepeatableRead transaction: ");
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString,
             System.Data.IsolationLevel.RepeatableRead);
         Console.WriteLine("-----------------------------------------------");

         Console.WriteLine("Demonstrate the Serializable transaction: ");
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString,
             System.Data.IsolationLevel.Serializable);
         Console.WriteLine("-----------------------------------------------");

         Console.WriteLine("Demonstrate the Snapshot transaction: ");
         OperateDatabase.SetSnapshot(connString, true);
         TransactionIsolationLevels.DemonstrateIsolationLevel(connString,
             System.Data.IsolationLevel.Snapshot);
         Console.WriteLine("-----------------------------------------------");

         Console.WriteLine("Demonstrate the difference between the Snapshot and Serializable transactions:");
         TransactionIsolationLevels.DemonstrateBetweenSnapshotAndSerializable(connString);
         OperateDatabase.SetSnapshot(connString, false);
         Console.WriteLine();
      }
   }
}

유니버설 Windows 플랫폼
10 이후 사용 가능
.NET Framework
1.1 이후 사용 가능
맨 위로 이동
표시: