none
Problema com lock de transação no ado.net 2.0 RRS feed

  • Pergunta

  • Olá amigos!

    Depois de muitos testes e pesquisas sobre transações (isolationlevel, Tips, etc...) no SQL Server 2000 e 2005 ficou uma dúvida pendente.

     

    Na documentação do SQL Server 2000 é informado que definindo o nível de isolamento ReadUncommited, por exemplo, os dados que estão sendo alterados na transação não são "lockados", portanto, é possível ler os dados que estão sendo alterados na transação.

     

    O fato é que a única forma que consegui ler o registro que está sendo alterado na transação é usando o tip NOLOCK ou READPAST na instrução SELECT que está fora do scopo da transação (em outro arquivo), mas essa forma é inviável para a minha aplicação pela quantidade de instruções SQL e stored procedures que estão distribuídas por toda a aplicação.

     

    Estou testando no windows xp sp2. Li um artigo em inglês que informa que no COM+ 1.0 (Windows 2000) não é possível alterar o isolation level e o mesmo é definido sempre como SERIALIZABLE. Estou achando que quando altero o isolation level para qualquer outro ele na verdade não está alterando e por isso não consigo ler os dados que estão sendo alterados na transação.

     

    Alguém tem uma idéia de como resolver?

     

    Para testar fiz um script q inicia uma transação depois dei um sleep de 1 minuto dentro do scopo da transação e defini o timeout do objeto command para 10 segundos assim se os dados estão lockados é disparada uma exception "Timeout expired".

     

    Segue o código que utilizei para testar abaixo...

     

    Página iniciatransacao.aspx

    Code Snippet

    Dim opcoes As TransactionOptions

    opcoes.IsolationLevel = IsolationLevel.ReadUncommitted

    opcoes.Timeout = TimeSpan.FromMinutes(10)

     

    Dim Escopo As New System.Transactions.TransactionScope(TransactionScopeOption.Required, opcoes)

    Using Escopo

    Try

    Dim SQL As New SQL

    Dim dt As Data.DataTable = SQL.Executar("SELECT * FROM teste")

     

    For i As Integer = 0 To dt.Rows.Count - 1

    Response.Write(dt.Rows(i)("campo1").ToString & "<br>")

    Next

     

    SQL.Executar("INSERT INTO teste (campo1, campo2, campo3, campo4) VALUES ('teste','teste','teste','teste')")

     

    SQL.Executar("UPDATE teste SET campo1 = '14' WHERE id = 14")

     

    Threading.Thread.Sleep(TimeSpan.FromSeconds(60)) 'Dorme por 1 minuto

     

    'Aqui simula um erro para dar um rollback

    SQL.Executar("INSERT INT teste (campo1, campo2, campo3, campo4) VALUES ('teste2','teste2','teste2','teste2')")

     

    Response.Write("TOTAL DE LINHAS: " & SQL.Executar("SELECT COUNT(*) FROM teste", True))

     

    Escopo.Complete()

    Catch ex As Exception

    Response.Write(ex.Message)

    End Try

    End Using

     

    Página listaregistros.aspx

    Code Snippet

    Try

    Dim SQL As New SQL

    Dim dt As Data.DataTable = SQL.Executar("SELECT * FROM teste")

     

    For i As Integer = 0 To dt.Rows.Count - 1

    Response.Write(dt.Rows(i)("campo1").ToString & "<br>")

    Next

     

    Response.Write("TOTAL DE LINHAS: " & SQL.Executar("SELECT COUNT(*) FROM teste", True))

     

    Response.Write("<BR>CONCLUIDO")

    Catch ex As Exception

    Response.Write(ex.Message)

    End Try

     

    Dentro da função Executar da classe SQL defini o timeout do objeto SqlCommand para 10 segundos, assim após 10 segundos executando, se a a tabela teste estiver lockada dará um erro.

    terça-feira, 4 de setembro de 2007 12:25

Respostas

Todas as Respostas

  • Ola Fabio,

    Desculpe-me, mas ainda não tive um tempo para analisar com calma o seu problema.

     

    terça-feira, 4 de setembro de 2007 14:17
  • Obrigado pela atenção Israel, o tópico é meio extenso mesmo, mas se alguém tiver qualquer idéia pra me passar agradeço muito...

     

    terça-feira, 4 de setembro de 2007 15:49
  • Fábio, a confusão que você fez é mais comum do que você imagina.

     

    O escopo ReadUncommitted significa que sua transação atual pode ler as alterações de outras transações. Isso é diferente da sua interpretação, pela qual outras transações podem ler os dados da transação atual.

     

    Percebe? É exatamente o oposto.

     

    Assim, o escopo ReadUncommitted tem que ser usado na transação que lê os dados, não na que está gravando os dados!

     

    Veja mais detalhes em http://bloggingabout.net/blogs/dennis/archive/2006/12/18/system-transactions-readuncommitted.aspx

     

    terça-feira, 4 de setembro de 2007 17:43
  • Olá Igor,

    Muito obrigado pela atenção!

     

    Não queria acreditar que funcionava dessa forma. Já havia feito um teste executando uma transação com isolationlevel serializable e outra com readuncommited e realmente funciona normalmente.

     

    Então não tem geito, a única forma de ler os dados que estão lockados por uma transação é definindo o tipo de isolamento em todos os selects que for dar fora dessa transação ou colocá-los em uma transação também, conforme descrito no link que você passou?

    terça-feira, 4 de setembro de 2007 18:42
  •  

    É exatamente isso.
    terça-feira, 4 de setembro de 2007 20:22