segunda-feira, 8 de setembro de 2014

Consultando apenas os registros "sujos" em uma tabela com Microsoft SQL Server

Lidando com bancos de dados podemos controlar as transações e a maneira como podemos acessar os dados em transações concorrentes.

Os níveis de isolamento de transação e os comandos para tais serão discutidos em um próximo post, porém, resumidamente, temos (Serializável, snapshot, repeatable read, read commited, read uncommited).

Dirty read (read uncommited ou nolock) nos permitem visualizar os dados de uma tabela mesmo sendo sujos (alterados em outras transações). Isso garante, com certo nível de inconsistência se as transações forem desprezadas e o  rollback usado, uma leitura o mais rápido possível dos dados no seu estado atual quase que em tempo real.

No entanto, como separar os dados "sujos" daqueles que já estavam gravados e commitados?
Imagine que você tem um ambiente onde um sistema legado permite que a aplicação seja fechada, após uma exception ou queda de rede, sem dar commit ou rollback nas transações correntes. Você rapidamente ficaria com várias transações em aberto, utilizando recursos do servidor e dando table locks ou situações de deadlock. Como saber quais são os dados não commitados?

Em um cenário real, como saber quais dados podem não ser consistentes porque estão sendo alterados neste momento, em uma transação ainda não finalizada?

O comando / table hint nolock depois do nome da tabela nos permite fazer uma dirty read e visualizar tanto os dados antigos (commitados) como os não commitados.  Já o comando readpast faz uma leitura sem lock (somente leitura) da tabela trazendo apenas os dados commitados. Então, para sabermos os dados não comitados basta usar not exist ou except.

Dado o seguinte cenário:

create table teste
(
 valor varchar(50)
)

insert into teste values ('comitado')
select * from teste



begin transaction  --rollback
insert into teste values ('nao comitado')




Not Exist

select * from teste(nolock) where valor not in (select valor from teste (READPAST ))




Except

O Except funciona como not in ou not exists, mas sem especificar uma coluna ou pk: você simplesmente especifica a query com os resultados que você NÃO quer que apareça.
SELECT * FROM teste WITH (nolock)
EXCEPT
SELECT * FROM teste WITH (READPAST)


Com esses comandos você pode verificar quais são os comandos "sujos" de transações ainda não "commitadas" do seu banco de dados. O except ainda te ajudará com relatórios mais elaborados onde você deverá especificar com um filtro complexo um conjunto de resultados que você não quer trazer na sua consulta mas não tem uma chave primária ou não tem exatamente um campo único para comparar.




photo credit: tec_estromberg via photopin cc

Postagens populares

Marcadores

delphi (60) C# (31) poo (21) Lazarus (19) Site aos Pedaços (15) sql (13) Reflexões (10) .Net (9) Humor (9) javascript (9) ASp.Net (8) api (8) Básico (6) Programação (6) ms sql server (5) Web (4) banco de dados (4) HTML (3) PHP (3) Python (3) design patterns (3) jQuery (3) livros (3) metaprogramação (3) Ajax (2) Debug (2) Dicas Básicas Windows (2) Pascal (2) games (2) linguagem (2) música (2) singleton (2) tecnologia (2) Anime (1) Api do Windows (1) Assembly (1) Eventos (1) Experts (1) GNU (1) Inglês (1) JSON (1) SO (1) datas (1) developers (1) dicas (1) easter egg (1) firebird (1) interfaces (1) introspecção (1) memo (1) oracle (1) reflexão (1)