Diferença entre "leitura confirmada" e "leitura repetível"

245

Eu acho que os níveis de isolamento acima são tão parecidos. Alguém poderia descrever com alguns exemplos bons qual é a principal diferença?

Fore
fonte
3
Você deve expandir a questão e adicionar tags para o "nível de isolamento" ao qual você está se referindo (Java, etc). "nível de isolamento" é um termo um tanto ambíguo, e você obviamente está pedindo uma resposta para um ambiente específico.
Jsup 27/10

Respostas:

564

A leitura confirmada é um nível de isolamento que garante que qualquer leitura de dados foi confirmada no momento. Simplesmente restringe o leitor a ver qualquer leitura intermediária, não confirmada e "suja". Não há nenhuma promessa de que, se a transação reemitir a leitura, encontrará os mesmos dados, os dados poderão sofrer alterações após serem lidos.

A leitura repetida é um nível de isolamento mais alto, que, além das garantias do nível de leitura confirmada, também garante que qualquer leitura de dados não possa ser alterada . Se a transação ler os mesmos dados novamente, os dados lidos anteriormente serão mantidos inalterados e disponível para leitura.

O próximo nível de isolamento, serializável, oferece uma garantia ainda mais forte: além de todas as garantias de leitura repetível, também garante que nenhum dado novo possa ser visto por uma leitura subsequente.

Digamos que você tenha uma tabela T com uma coluna C com uma linha, digamos que tenha o valor '1'. E considere que você tem uma tarefa simples como a seguinte:

BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;

Essa é uma tarefa simples que emite duas leituras da tabela T, com um atraso de 1 minuto entre elas.

  • em READ COMMITTED, o segundo SELECT pode retornar qualquer dado. Uma transação simultânea pode atualizar o registro, excluí-lo e inserir novos registros. A segunda seleção sempre verá os novos dados.
  • em REPEATABLE READ, o segundo SELECT é garantido para exibir pelo menos as linhas retornadas do primeiro SELECT inalteradas . Novas linhas podem ser adicionadas por uma transação simultânea naquele minuto, mas as linhas existentes não podem ser excluídas nem alteradas.
  • em lê SERIALIZABLE, a segunda seleção é garantida para ver exatamente as mesmas linhas que a primeira. Nenhuma linha pode mudar, nem ser excluída, nem novas linhas podem ser inseridas por uma transação simultânea.

Se você seguir a lógica acima, poderá perceber rapidamente que as transações SERIALIZABLE, embora possam facilitar a sua vida, estão sempre bloqueando completamente todas as operações simultâneas possíveis, pois exigem que ninguém possa modificar, excluir ou inserir nenhuma linha. O nível de isolamento de transação padrão do System.Transactionsescopo .Net é serializável, e isso geralmente explica o desempenho péssimo resultante.

E, finalmente, há também o nível de isolamento do INSTANTÂNEO. O nível de isolamento do INSTANTÂNEO oferece as mesmas garantias que os serializáveis, mas não exigindo que nenhuma transação simultânea possa modificar os dados. Em vez disso, força todos os leitores a ver sua própria versão do mundo (é o próprio 'instantâneo'). Isso facilita muito a programação, além de ser muito escalável, pois não bloqueia atualizações simultâneas. No entanto, esse benefício tem um preço: consumo extra de recursos do servidor.

Leituras complementares:

Remus Rusanu
fonte
24
Acho que há um erro acima em REPEATABLE READ: Você diz que as linhas existentes não podem ser excluídas nem alteradas, mas acho que elas podem ser excluídas ou alteradas porque a leitura repetível simplesmente lê um "instantâneo" e não os dados reais. Nos documentos dev.mysql.com/doc/refman/5.0/en/… : "Todas as leituras consistentes na mesma transação leem o instantâneo estabelecido pela primeira leitura."
Derek Litz
2
@Derek Litz Estou certo no que você está dizendo: Os dados podem / podem ser alterados por terceiros enquanto a transação está ocorrendo, mas as leituras ainda verão os dados originais 'antigos' como se a alteração não tivesse ocorrido local (o instantâneo).
Programster
5
@Talos de milho. Sim, leituras fantasmas podem ocorrer a partir de exclusões (ou inserções). Sim, leituras fantasmas podem ocorrer com isolamento de leitura repetível (somente a partir de inserções). Não, leituras fantasmas de exclusões não podem ocorrer em isolamento de leitura repetível. Teste-o. O que estou dizendo não é contradito pela documentação que você citou.
AndyBrown
4
@Cornstalks NP. Eu só mencionei isso porque não tinha 100% de certeza e tive que me aprofundar para ter certeza de quem estava certo! E não queria que futuros leitores fossem enganados. Re mantendo os comentários, provavelmente é melhor manter como sugerido. Tenho certeza de que qualquer pessoa interessada nesse nível de detalhes será suficientemente específica para ler todos os comentários!
AndyBrown
12
Obrigado por não excluir seus comentários. A discussão ajuda a conectar mais pontos.
21715 Josh
68

Leitura Repetível

O estado do banco de dados é mantido desde o início da transação. Se você recuperar um valor na sessão1, atualize esse valor na sessão2, recuperando-o novamente na sessão1 retornará os mesmos resultados. As leituras são repetíveis.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Aaron

Leitura confirmada

No contexto de uma transação, você sempre recuperará o valor confirmado mais recentemente. Se você recuperar um valor na sessão1, atualizá-lo na sessão2 e recuperá-lo na sessão1 novamente, você obterá o valor modificado na sessão2. Ele lê a última linha confirmada.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Bob

Faz sentido?

Hazel_arun
fonte
Tentei a leitura repetida no SQL Server 2008 com "definir leitura repetível do nível de isolamento". Criou duas janelas de consulta sql. Mas não funcionou. Por quê?
Aditya Bokade
1
Por que a segunda sessão1 ainda leria Aaron? A transação da session2 não foi concluída e confirmada? Eu sei disso, mas talvez alguém possa lançar alguma luz.
Sonny Childs
9
Acho que a leitura repetida bloqueará a segunda sessão até a primeira sessão confirmada. Então o exemplo está errado.
Nighon
4
No caso de Leitura Repetível, quando a sessão 1 lê a linha, coloca um bloqueio compartilhado, que não permitiria nenhum bloqueio Exclusivo (para a sessão 2) para atualização, portanto, os dados não podem ser atualizados.
Taher
Acho servidor SQL e MySQL comportam de forma diferente quando se trata de atualização de linhas compartilhadas entre duas transações
user2488286
23

Simplesmente a resposta de acordo com a minha leitura e compreensão para este tópico e a resposta @ remus-rusanu é baseada neste cenário simples:

Existem dois processos A e B. O processo B está lendo a Tabela X O processo A está escrevendo na tabela X O processo B está lendo novamente a Tabela X.

  • ReadUncommit : O processo B pode ler dados não confirmados do processo A e pode ver linhas diferentes com base na gravação B. Nenhum bloqueio
  • ReadCommitted : o processo B pode ler SOMENTE dados confirmados do processo A e pode ver linhas diferentes com base na gravação apenas de COMMITTED B. podemos chamá-lo de bloqueio simples?
  • RepeatableRead : o processo B lerá os mesmos dados (linhas), independentemente do processo A. Mas o processo A pode alterar outras linhas. Bloco de nível de linhas
  • Serializável : O processo B lê as mesmas linhas de antes e o processo A não pode ler ou gravar na tabela. Bloco no nível da tabela
  • Instantâneo : todo processo tem sua própria cópia e eles estão trabalhando nele. Cada um tem sua própria visão
Mo Zaatar
fonte
15

Pergunta antiga que já tem uma resposta aceita, mas eu gosto de pensar nesses dois níveis de isolamento em termos de como eles alteram o comportamento de bloqueio no SQL Server. Isso pode ser útil para aqueles que estão depurando impasses como eu.

LER COMPROMISSO (padrão)

Bloqueios compartilhados são obtidos no SELECT e liberados quando a instrução SELECT é concluída . É assim que o sistema pode garantir que não haja leituras sujas de dados não confirmados. Outras transações ainda podem alterar as linhas subjacentes após a conclusão de seu SELECT e antes de sua transação.

LEITURA REPETÍVEL

Os bloqueios compartilhados são obtidos no SELECT e liberados somente após a transação ser concluída . É assim que o sistema pode garantir que os valores que você lê não sejam alterados durante a transação (porque permanecem bloqueados até que a transação seja concluída).

Chris Gillum
fonte
13

Tentando explicar essa dúvida com diagramas simples.

Leitura confirmada : aqui neste nível de isolamento, a transação T1 estará lendo o valor atualizado do X confirmado pela transação T2.

Leitura confirmada

Leitura Repetível: Nesse nível de isolamento, a Transação T1 não considerará as alterações confirmadas pela Transação T2.

insira a descrição da imagem aqui

vkrishna17
fonte
1

Penso que esta imagem também pode ser útil, ajuda-me como referência quando quero recordar rapidamente as diferenças entre os níveis de isolamento (graças a kudvenkat no youtube)

insira a descrição da imagem aqui

Ivan Pavičić
fonte
0

Por favor note que, a repetível no que diz respeito leitura repetida para uma tupla, mas não para a tabela inteira. Nos níveis de isolamento do ANSC, pode ocorrer anomalia na leitura fantasma , o que significa que ler uma tabela com a mesma cláusula where duas vezes pode retornar diferentes retornos e diferentes conjuntos de resultados. Literalmente, não é repetível .

不辞 长 做 岭南 人
fonte
-1

Minha observação sobre a solução inicial aceita.

Sob RR (padrão mysql) - Se um tx estiver aberto e um SELECT for acionado, outro tx NÃO poderá excluir nenhuma linha pertencente ao conjunto de resultados READ anteriores até que o tx anterior seja confirmado (na verdade, a instrução de exclusão no novo tx será interrompida) , no entanto, a próxima TX pode excluir todas as linhas da tabela sem nenhum problema. Btw, uma próxima leitura no TX anterior ainda verá os dados antigos até que sejam confirmados.

Sanjeev Dhiman
fonte
2
Você pode colocá-lo na seção de comentários para que o respondente seja notificado. Dessa forma, ele será capaz de responder às suas observações e fazer as correções, se necessário.
RBT