Usuário com melhor resposta
Problema com lock de transação no ado.net 2.0

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 SnippetDim 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()
Response.Write(ex.Message)
End Try
End Using
Página listaregistros.aspx
Code SnippetTry
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.
Respostas
-
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
Todas as Respostas
-
-
-
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
-
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?
-