1

테이블에 새 행을 삽입하는 SQL 트랜잭션이 매우 느립니다. 다른 연결의 다른 모든 "선택"쿼리는 테이블의 잠금을 해제하기 위해이 트랜잭션을 기다립니다.느린 SQL 트랜잭션 블록 테이블

첫 번째 트랜잭션이 작동하는 동안 테이블에서 오래된 행을 가져올 수 있습니까?

SqlExpress 2008 R2. exapmle를 들어 :

private void button1_Click(object sender, EventArgs e) 
    { 
     System.Threading.Thread t = new System.Threading.Thread(
      delegate() 
      { 
       var conn = new SqlConnection(@"Data Source=ARTNB\SQLEXPRESS;Initial Catalog=test;User ID=**;Password=******"); 
       conn.Open(); 
       var cmd = conn.CreateCommand(); 
       var tr = conn.BeginTransaction(IsolationLevel.RepeatableRead, "test"); 
       cmd.Transaction = tr; 
       cmd.CommandText = @"INSERT INTO Cards (SerialNumber,OperationID,TariffID,RequestTime,State,AgentInfo) VALUES('1213','345',13, GETDATE(),1,'')"; 
       cmd.ExecuteNonQuery(); 
       //very slow transaction 
       System.Threading.Thread.Sleep(300000); 
       tr.Commit(); 
       conn.Close(); 
      }); 
     t.Start(); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     var conn = new SqlConnection(@"Data Source=ARTNB\SQLEXPRESS;Initial Catalog=test;User ID=**;Password=******"); 
     conn.Open(); 
     var cmd = conn.CreateCommand(); 
     var tr = conn.BeginTransaction(IsolationLevel.RepeatableRead, "test2"); 
     cmd.Transaction = tr; 
     cmd.CommandText = @"SELECT COUNT(*) FROM Cards"; 
     var r = cmd.ExecuteReader(); 
     r.Read(); 
     r.Close(); 
     tr.Commit(); 
     conn.Close(); 
    } 

button2_Click 방법은 내가 테이블에 새 행을 삽입하는 매우 느린 SQL 트랜잭션을 가지고 커밋 것은 대기, immidiately 행을 가져 doesnt't. 다른 연결의 다른 모든 "선택"쿼리는 테이블의 잠금을 해제하기 위해이 트랜잭션을 기다립니다.

첫 번째 트랜잭션이 작동하는 동안 테이블에서 오래된 행을 가져올 수 있습니까?

SqlExpress 2008 R2. exapmle 들어 :

private void button1_Click(object sender, EventArgs e) 
    { 
     System.Threading.Thread t = new System.Threading.Thread(
      delegate() 
      { 
       var conn = new SqlConnection(@"Data Source=ARTNB\SQLEXPRESS;Initial Catalog=test;User ID=**;Password=******"); 
       conn.Open(); 
       var cmd = conn.CreateCommand(); 
       var tr = conn.BeginTransaction(IsolationLevel.RepeatableRead, "test"); 
       cmd.Transaction = tr; 
       cmd.CommandText = @"INSERT INTO Cards (SerialNumber,OperationID,TariffID,RequestTime,State,AgentInfo) VALUES('1213','345',13, GETDATE(),1,'')"; 
       cmd.ExecuteNonQuery(); 
       //very slow transaction 
       System.Threading.Thread.Sleep(300000); 
       tr.Commit(); 
       conn.Close(); 
      }); 
     t.Start(); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     var conn = new SqlConnection(@"Data Source=ARTNB\SQLEXPRESS;Initial Catalog=test;User ID=**;Password=******"); 
     conn.Open(); 
     var cmd = conn.CreateCommand(); 
     var tr = conn.BeginTransaction(IsolationLevel.RepeatableRead, "test2"); 
     cmd.Transaction = tr; 
     cmd.CommandText = @"SELECT COUNT(*) FROM Cards"; 
     var r = cmd.ExecuteReader(); 
     r.Read(); 
     r.Close(); 
     tr.Commit(); 
     conn.Close(); 
    } 

button2_Click 메서드는 스레드를 Button1_Click 커밋 기다리며 immidiately 행 페치 doesnt't.

+0

당신은 dbo.TableName WITH (NOLOCK) FROM'SELECT (열) ...'같은 테이블 힌트를 사용할 수 있습니다 - [테이블 힌트에 MSDN 온라인 설명서]를 참조 (http://msdn.microsoft.com/en- us/library/ms187373.aspx) - 당신이 알아야 할 다른 단점이 있습니다 –

답변

3

하나의 빠른 'get out of jail'카드가 Deadlocked!에 언급 된 Choosing Row Versioning-based Isolation Levels을 참조하여 데이터베이스에서 읽기 커밋 된 스냅 샷을 활성화합니다. RCSI가 데이터베이스에서 활성화되면 butonn2 클릭 읽기가 원하는대로 정확하게 수행됩니다. 이전 행을 읽습니다. 단, button1이 커밋되기를 기다리지 않아도됩니다.

는 RCSI 단순히이 한 번 실행 사용하려면 다음 행 버전 관리를 활성화하면 tempdb의 IO 크기에 비용을 발생합니다 물론

ALTER DATABASE [test] SET READ_COMMITTED_SNAPSHOT ON; 

는 공짜가 없다. Row Versioning Resource Usage을 참조하십시오. Express 인스턴스의 경우 측정 가능한 영향은 없습니다.

+0

+1 - 명확히 해 주셔서 감사합니다. 잘못된 대답이 삭제되었습니다. – JNK

+0

READPAST : SELECT COUNT (*) FROM 카드 (READPAST)는 오래된 행만 집계 할 수 있습니다. – user879096

+0

READPAST도 작동하지만 대신 read_committed_snpashot를 활성화하는 것이 좋습니다. –