none
select com nolock retorna os dados enquanto que select sem nolock não retorna os dados RRS feed

  • Pergunta

  • Estão ocorrendo duas situação que nunca vi:

    1) Porque quando executo um select com nolock os dados são retornados

    e quando executo sem o nolock os dados não são retornados?

    select * from tabela                <=  não retorna nada

    select * from tabela (nolock)   <= retorna os registros

    2) Quando executo um update sem especificar a chave o comando não é efetivado

    e quanto eu executo o comando update para uma especifica chave o comando é efetivado ... porque?

    update tabela set coluna1=valor  <= não funciona/efetiva

    update tabela set coluna1=valor where coluna_chave=valor_chave  <= funciona/efetiva

    Se alguém puder me ajudar desde já muito obrigado.

    sábado, 21 de julho de 2012 02:20

Respostas

  • Boa Noite,

    Um banco de dados tem diversas operações concorrentes entre si e essas operácões concorrem por vários recursos comuns (registros, páginas, tabelas, etc). Como há várias operações fazendo alterações e leituras no mesmos recursos, nem sempre é possível que elas o façam ao mesmo tempo (isso poderia comprometer a integridade do SGBD). Nessas situações, existem as "travas" (locks) que são impostas sobre os recursos para que operações concorrentes não os acessem ao mesmo tempo em situações que possam comprometê-los.

    Quando uma sessão impõe uma trava (lock) sobre um recurso e outra sessão deseja utilizar esse recurso, a primeira sessão impõe um bloqueio sobre a outra (block) e dizemos que a segunda sessão está bloqueada pela primeira sessão. Nesse caso, a segunda sessão é o processo bloqueado (blocked process) e a primeira é o processo bloqueador (blocking process).

    Você pode dispensar o bloqueio e desrespeitar a trava quando opta por incluir o HINT NOLOCK em suas consultas. No momento em que você colocou o HINT NOLOCK na consulta, você disse em outras palavras que deseja que essa consulta não irá respeitar a trava e irá ler os dados da tabela do jeito que eles estão. Isso aparentemente dá mais performance, uma vez que a leitura não irá esperar que a trava suma ou que o processo bloqueador termine de fazer o que estava fazendo e essa é a razão pela qual muitas pessoas colocam esse HINT em tudo quanto é consulta. Entretanto, temos de lembrar que "ler os dados do jeito que estão" incorre em inconsistências em potencial, pois, é possível que eles estejam sofrendo alterações que sofrerão um ROLLBACK e nesse caso você leu coisas que não foram de fato efetivadas (fenômemo conhecido como leitura suja).

    No momento em que você executou a SELECT * FROM Tabela e não obteve os resultados e com o NOLOCK conseguiu efetivar a consulta, provavelmente você estava bloqueado e por isso não ela não conclui. Veja que para efetuar uma consulta na tabela inteira (sem cláusula WHERE), você precisa impor uma trava de leitura nela inteira. Se alguém estiver alterando uma linha que seja, você não conseguirá impor essa trava. Quando você colocou o NOLOCK, você simplesmente disse "sem travas" e por isso funciona.

    No caso do UPDATE, a situação é a mesma. Um UPDATE sem cláusula WHERE, precisa impor uma trava (LOCK) de escrita na tabela inteira e se houver alguém alterando ou lendo um único registro, você também não conseguirá impor essa trava e por isso o comando não conclui. No momento em que você colocou uma cláusula WHERE com uma coluna chave, você informou que desejar alterar apenas uma linha e por isso, a trava será imposta apenas aquela linha. Considerando que não há ninguém lendo ou alterando aquela linha, você consegue impor a trava e concluir a sua operação.

    Para que suas instruções de SELECT e UPDATE possam funcionar, é preciso que ninguém esteja impondo travas e bloqueando sua sessão. Em algum momento isso vai acontecer, mas em sistemas muito concorrentes isso pode não ser tão imediato ou demorar um pouco mais do que você gostaria. Se uma sessão bloqueia outra, que bloqueia outra que bloqueia outra e assim sucessivamente, você pode ter uma longa cadeia de bloqueios e aí dará a impressão de estar tudo "travado". O negócio é tentar descobrir porque isso acontece e tentar resolver. Transações muito longas por exemplo potencializam esse efeito.

    Para entender um pouco mais sobre esse assunto, eu sugiro fortemente que você faça uma visita no meu canal do Youtube. Há muitos vídeos relacionados com esse assunto. Sugiro a lista de concorrência de dados disponível em:

    http://www.youtube.com/playlist?list=PL70D92D06E08E6653&feature=plcp

    [ ]s,

    Gustavo Maia Aguiar
    Blog: http://gustavomaiaaguiar.wordpress.com
    Vídeos:http://www.youtube.com/user/gmasql


    Classifique as respostas. O seu feedback é imprescindível

    • Sugerido como Resposta Gustavo Maia Aguiar segunda-feira, 23 de julho de 2012 00:45
    • Marcado como Resposta Harley Araujo segunda-feira, 23 de julho de 2012 13:04
    segunda-feira, 23 de julho de 2012 00:45

Todas as Respostas

  • Boa Noite,

    Um banco de dados tem diversas operações concorrentes entre si e essas operácões concorrem por vários recursos comuns (registros, páginas, tabelas, etc). Como há várias operações fazendo alterações e leituras no mesmos recursos, nem sempre é possível que elas o façam ao mesmo tempo (isso poderia comprometer a integridade do SGBD). Nessas situações, existem as "travas" (locks) que são impostas sobre os recursos para que operações concorrentes não os acessem ao mesmo tempo em situações que possam comprometê-los.

    Quando uma sessão impõe uma trava (lock) sobre um recurso e outra sessão deseja utilizar esse recurso, a primeira sessão impõe um bloqueio sobre a outra (block) e dizemos que a segunda sessão está bloqueada pela primeira sessão. Nesse caso, a segunda sessão é o processo bloqueado (blocked process) e a primeira é o processo bloqueador (blocking process).

    Você pode dispensar o bloqueio e desrespeitar a trava quando opta por incluir o HINT NOLOCK em suas consultas. No momento em que você colocou o HINT NOLOCK na consulta, você disse em outras palavras que deseja que essa consulta não irá respeitar a trava e irá ler os dados da tabela do jeito que eles estão. Isso aparentemente dá mais performance, uma vez que a leitura não irá esperar que a trava suma ou que o processo bloqueador termine de fazer o que estava fazendo e essa é a razão pela qual muitas pessoas colocam esse HINT em tudo quanto é consulta. Entretanto, temos de lembrar que "ler os dados do jeito que estão" incorre em inconsistências em potencial, pois, é possível que eles estejam sofrendo alterações que sofrerão um ROLLBACK e nesse caso você leu coisas que não foram de fato efetivadas (fenômemo conhecido como leitura suja).

    No momento em que você executou a SELECT * FROM Tabela e não obteve os resultados e com o NOLOCK conseguiu efetivar a consulta, provavelmente você estava bloqueado e por isso não ela não conclui. Veja que para efetuar uma consulta na tabela inteira (sem cláusula WHERE), você precisa impor uma trava de leitura nela inteira. Se alguém estiver alterando uma linha que seja, você não conseguirá impor essa trava. Quando você colocou o NOLOCK, você simplesmente disse "sem travas" e por isso funciona.

    No caso do UPDATE, a situação é a mesma. Um UPDATE sem cláusula WHERE, precisa impor uma trava (LOCK) de escrita na tabela inteira e se houver alguém alterando ou lendo um único registro, você também não conseguirá impor essa trava e por isso o comando não conclui. No momento em que você colocou uma cláusula WHERE com uma coluna chave, você informou que desejar alterar apenas uma linha e por isso, a trava será imposta apenas aquela linha. Considerando que não há ninguém lendo ou alterando aquela linha, você consegue impor a trava e concluir a sua operação.

    Para que suas instruções de SELECT e UPDATE possam funcionar, é preciso que ninguém esteja impondo travas e bloqueando sua sessão. Em algum momento isso vai acontecer, mas em sistemas muito concorrentes isso pode não ser tão imediato ou demorar um pouco mais do que você gostaria. Se uma sessão bloqueia outra, que bloqueia outra que bloqueia outra e assim sucessivamente, você pode ter uma longa cadeia de bloqueios e aí dará a impressão de estar tudo "travado". O negócio é tentar descobrir porque isso acontece e tentar resolver. Transações muito longas por exemplo potencializam esse efeito.

    Para entender um pouco mais sobre esse assunto, eu sugiro fortemente que você faça uma visita no meu canal do Youtube. Há muitos vídeos relacionados com esse assunto. Sugiro a lista de concorrência de dados disponível em:

    http://www.youtube.com/playlist?list=PL70D92D06E08E6653&feature=plcp

    [ ]s,

    Gustavo Maia Aguiar
    Blog: http://gustavomaiaaguiar.wordpress.com
    Vídeos:http://www.youtube.com/user/gmasql


    Classifique as respostas. O seu feedback é imprescindível

    • Sugerido como Resposta Gustavo Maia Aguiar segunda-feira, 23 de julho de 2012 00:45
    • Marcado como Resposta Harley Araujo segunda-feira, 23 de julho de 2012 13:04
    segunda-feira, 23 de julho de 2012 00:45
  • Gustavo desde já obrigado pela atenção e pela resposta.

    Eu reindexei a tabela e tudo voltou ao normal.

    segunda-feira, 23 de julho de 2012 11:34