Qual é a diferença entre leitura não repetível e leitura fantasma?

154

Qual é a diferença entre leitura não repetível e leitura fantasma?

Eu li o artigo Isolamento (sistemas de banco de dados) da Wikipedia , mas tenho algumas dúvidas. No exemplo abaixo, o que acontecerá: a leitura não repetível e a leitura fantasma ?

Transação A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1
RESULTADO:
1----MIKE------29019892---------5000
Transação B
UPDATE USERS SET amount=amount+5000 where ID=1 AND accountno=29019892;
COMMIT;
Transação A
SELECT ID, USERNAME, accountno, amount FROM USERS WHERE ID=1

Outra dúvida é, no exemplo acima, qual nível de isolamento deve ser usado? E porque?

user1357722
fonte

Respostas:

165

Da Wikipedia (que tem exemplos ótimos e detalhados para isso):

Uma leitura não repetível ocorre quando, durante o curso de uma transação, uma linha é recuperada duas vezes e os valores dentro da linha diferem entre as leituras.

e

Uma leitura fantasma ocorre quando, no decorrer de uma transação, duas consultas idênticas são executadas e a coleção de linhas retornadas pela segunda consulta é diferente da primeira.

Exemplos simples:

  • O usuário A executa a mesma consulta duas vezes.
  • Nesse meio tempo, o usuário B executa uma transação e confirma.
  • Leitura não repetível: a linha A que o usuário A consultou tem um valor diferente na segunda vez.
  • Leitura fantasma: todas as linhas da consulta têm o mesmo valor antes e depois, mas linhas diferentes estão sendo selecionadas (porque B excluiu ou inseriu algumas). Exemplo: select sum(x) from table;retornará um resultado diferente, mesmo que nenhuma das linhas afetadas tenha sido atualizada, se as linhas foram adicionadas ou excluídas.

No exemplo acima, qual nível de isolamento deve ser usado?

Qual o nível de isolamento necessário depende do seu aplicativo. Há um alto custo para um nível de isolamento "melhor" (como concorrência reduzida).

No seu exemplo, você não terá uma leitura fantasma, porque seleciona apenas uma única linha (identificada pela chave primária). Você pode ter leituras não repetíveis. Se isso for um problema, convém ter um nível de isolamento que impeça isso. No Oracle, a transação A também pode emitir um SELECT FOR UPDATE; a transação B não pode alterar a linha até que A seja concluído.

Thilo
fonte
6
Eu realmente não entendo a lógica de tal sintaxe ... A não-repetíveis leitura ocorre quando a leitura é repetida (e um valor diferente obtidos) ?? ...!
Serhio
14
@serhio "não repetitivo" refere-se ao fato de que você pode ler um valor uma vez e obter x como resultado e, em seguida, ler novamente e obter y como resultado, para que você não possa repetir (não repetível) os mesmos resultados de dois consultas separadas da mesma linha, porque esse valor da linha foi atualizado entre as leituras.
BateTech 9/09/15
@Thilo Algum exemplo real de caso de uso em que a leitura repetível pode criar problemas e onde é necessário?
user104309
E se o PK for modificado em outra transação? Isso poderia resultar em uma leitura fantasma? (Uma coisa estranha a fazer na maioria dos casos, mas não impossível.)
jpmc26
1
Ambos soa mesmo para mim
sn.anurag
125

Uma maneira simples de pensar sobre isso é:

As leituras não repetíveis e fantasmas têm a ver com operações de modificação de dados de uma transação diferente, que foram confirmadas após o início da transação e, em seguida, lidas pela transação.

Leituras não repetíveis são quando sua transação lê UPDATES confirmadas de outra transação. A mesma linha agora tem valores diferentes dos que tinham quando sua transação começou.

As leituras fantasmas são semelhantes, mas ao ler INSERTS e / ou DELETES confirmados de outra transação. Existem novas linhas ou linhas que desapareceram desde que você iniciou a transação.

As leituras sujas são semelhantes às leituras não repetíveis e fantasmas, mas estão relacionadas à leitura de dados NÃO COMPROMETIDOS, e ocorrem quando um UPDATE, INSERT ou DELETE de outra transação é lido e a outra transação ainda não confirmou os dados. Ele está lendo dados "em andamento", que podem não estar completos e nunca serem realmente confirmados.

BateTech
fonte
4
Tem a ver com os níveis de isolamento de transação e a simultaneidade. Usando o nível de isolamento padrão, você não terá leituras sujas e, na maioria dos casos, deseja evitar leituras sujas. Existem níveis de isolamento ou dicas de consulta que permitirão leituras sujas, o que, em alguns casos, é uma troca aceitável para obter maior concorrência ou é necessário devido a um caso extremo, como solucionar uma transação em andamento a partir de outra conexão. É bom que a idéia de uma leitura suja não passe no "teste de cheiro" para você, como regra geral, eles devem ser evitados, mas têm um objetivo.
BateTech
1
O @PHPAvenger aqui é um caso de uso para o nível de isolamento READ UNCOMMITTED: sempre existe a possibilidade de encontrar um conflito entre uma consulta de seleção e uma atualização (explicada aqui ). Se a consulta de seleção for muito complexa para criar um índice de cobertura, para evitar bloqueios, você desejará usar um nível de isolamento READ UNCOMMITED com o risco de encontrar leituras sujas, mas com que frequência você reverte transações para se preocupar com essas leituras sujas não sendo permanente ?!
petrica.martinescu
1
@ petrica.martinescu, os problemas causados ​​por leituras sujas NÃO são apenas sobre a reversão ou não de uma transação. Leituras sujas podem retornar resultados muito imprecisos, dependendo de como os dados nas transações pendentes foram modificados. Imagine uma transação que execute uma série de várias exclusões, atualizações e / ou inserções. Se você ler os dados no meio dessa transação usando "ler não confirmado", eles estarão incompletos. O nível de isolamento de instantâneo (no SQL Server) é uma alternativa muito melhor para leitura não confirmada. Um caso de uso válido para o nível de isolamento não confirmado de leitura em um sistema de produção é IMO raro.
BateTech 03/03
2
@DiponRoy ótima pergunta. O bloqueio implementado se estiver usando o isolamento de leitura repetível (RR) deve impedir a exclusão de exclusões nas linhas que foram selecionadas. Vi várias definições dos dois níveis de iso ao longo dos anos, principalmente dizendo que fantasma é uma alteração na coleção / # linhas retornadas e RR é a mesma linha sendo alterada. Acabei de verificar a documentação atualizada do MS SQL que diz que exclusões podem causar não-RR ( docs.microsoft.com/en-us/sql/odbc/reference/develop-app/… ), por isso acho que seria seguro agrupar exclusões em a categoria RR também
BateTech 26/04
2
@anir yes inserções e exclusões estão incluídas em leituras sujas. Exemplo: inicie uma transação, insira 2 de 100 linhas da fatura na conexão a, agora a conexão b lê essas 2 linhas antes que o trx seja confirmado e antes que as outras 98 linhas sejam adicionadas e, portanto, não inclua todas as informações da fatura. Isso seria uma leitura suja envolvendo uma inserção.
BateTech 24/03/19
28

Conforme explicado neste artigo , a anomalia de leitura não repetível tem a seguinte aparência:

insira a descrição da imagem aqui

  1. Alice e Bob iniciam duas transações de banco de dados.
  2. Bob lê o registro da postagem e o valor da coluna do título é Transações.
  3. Alice modifica o título de um determinado registro de postagem para o valor de ACID.
  4. Alice confirma sua transação de banco de dados.
  5. Se Bob reler o registro de postagem, ele observará uma versão diferente desta linha da tabela.

Em este artigo sobre leitura fantasma , você pode ver que esta anomalia pode acontecer o seguinte:

insira a descrição da imagem aqui

  1. Alice e Bob iniciam duas transações de banco de dados.
  2. Bob lê todos os registros post_comment associados à linha de postagem com o valor identificador 1.
  3. Alice adiciona um novo registro post_comment associado à linha de postagem com o valor identificador 1.
  4. Alice confirma sua transação de banco de dados.
  5. Se Bob reler os registros post_comment com o valor da coluna post_id igual a 1, ele observará uma versão diferente desse conjunto de resultados.

Portanto, enquanto a leitura não repetível se aplica a uma única linha, a leitura fantasma é sobre um intervalo de registros que atendem a um determinado critério de filtragem de consulta.

Vlad Mihalcea
fonte
3
superb visualization @Vlad
dextermini
23

Ler fenômenos

  • Leituras sujas : ler dados não autorizados de outra transação
  • Leituras não repetíveis : leia dados COMMITTED de umaUPDATEconsulta de outra transação
  • O Phantom lê : lê dados COMMITTED de umaINSERTouDELETEconsulta de outra transação

Nota : As instruções DELETE de outra transação também têm uma probabilidade muito baixa de causar leituras não repetíveis em certos casos. Isso acontece quando a instrução DELETE, infelizmente, remove a mesma linha que sua transação atual estava consultando. Mas esse é um caso raro e muito mais improvável de ocorrer em um banco de dados com milhões de linhas em cada tabela. As tabelas que contêm dados de transação geralmente têm alto volume de dados em qualquer ambiente de produção.

Também podemos observar que ATUALIZAÇÕES pode ser um trabalho mais frequente na maioria dos casos de uso do que INSERT ou DELETES reais (nesses casos, o risco de leituras não repetíveis permanece apenas - leituras fantasmas não são possíveis nesses casos). É por isso que as atualizações são tratadas de forma diferente de INSERT-DELETE e a anomalia resultante também é nomeada de maneira diferente.

Também há um custo de processamento adicional associado ao manuseio de INSERT-DELETEs, em vez de apenas manipular as ATUALIZAÇÕES.


Benefícios de diferentes níveis de isolamento

  • READ_UNCOMMITTED impede nada. É o nível de isolamento zero
  • READ_COMMITTED impede apenas um, ou seja, leituras sujas
  • REPEATABLE_READ evita duas anomalias: leituras sujas e leituras não repetíveis
  • SERIALIZABLE evita todas as três anomalias: leituras sujas, leituras não repetíveis e leituras fantasmas

Por que não definir a transação SERIALIZABLE o tempo todo? Bem, a resposta para a pergunta acima é: A configuração SERIALIZABLE torna as transações muito lentas , o que novamente não queremos.

De fato, o consumo de tempo de transação está na seguinte taxa:

SERIALIZABLE > REPEATABLE_READ > READ_COMMITTED > READ_UNCOMMITTED

Portanto, a configuração READ_UNCOMMITTED é a mais rápida .


Resumo

Na verdade, precisamos analisar o caso de uso e decidir um nível de isolamento para otimizar o tempo da transação e também evitar a maioria das anomalias.

Observe que os bancos de dados, por padrão, têm a configuração REPEATABLE_READ.

Subhadeep Ray
fonte
1
UPDATE ou DELETE podem ocorrer para leituras não repetíveis ou apenas UPDATE?
Dipon Roy
1
UPDATE ou DELETE tanto pode ter lugar para não-repetíveis
Niket patel
Na verdade, podemos resumir que, em média, uma instrução DELETE aleatória executada por outra transação no mesmo banco de dados tem uma probabilidade muito baixa de causar leituras não repetíveis para a transação atual. Mas a mesma instrução de exclusão tem 100% de chance de causar uma leitura fantasma para a transação atual. Pensando assim, minha escrita está um pouco errada, se você entender palavra por palavra. Mas, ei, intencionalmente, escrevi dessa maneira para tornar as coisas mais claras para o leitor.
Subhadeep Ray 11/04/19
+1 para uma explicação simples e fácil de entender. No entanto eu acho que a maioria dos bancos de dados (Oracle, MySQL) têm um nível de isolamento padrão de Read Committed e provavelmente postgress usos padrão de REPEATABLE_READ
akila
7

Há uma diferença na implementação entre esses dois tipos de níveis de isolamento.
Para "leitura não repetível", é necessário o bloqueio de linhas.
Para "leitura fantasma", é necessário o bloqueio de escopo, mesmo um bloqueio de tabela.
Podemos implementar esses dois níveis usando o protocolo de bloqueio de duas fases .

egraldlo
fonte
Para implementar leitura repetível ou serializável, não há necessidade de usar o bloqueio de linhas.
precisa saber é o seguinte
5

Em um sistema com leituras não repetíveis, o resultado da segunda consulta da Transação A refletirá a atualização na Transação B - verá o novo valor.

Em um sistema que permite leituras fantasmas, se a Transação B inserir uma nova linha com ID = 1, a Transação A verá a nova linha quando a segunda consulta for executada; isto é, leituras fantasmas são um caso especial de leitura não repetível.

Jeffrey Kemp
fonte
Não acho que a explicação de uma leitura fantasma esteja correta. Você pode obter leituras fantasmas, mesmo que dados não confirmados nunca estejam visíveis. Veja o exemplo na Wikipedia (link nos comentários acima).
Thilo
1

A resposta aceita indica acima de tudo que a chamada distinção entre os dois não é realmente significativa.

Se "uma linha é recuperada duas vezes e os valores dentro da linha diferem entre as leituras", eles não são a mesma linha (não é a mesma tupla na fala correta do RDB) e é, por definição, também o caso em que "a coleção de linhas retornadas pela segunda consulta são diferentes da primeira ".

Quanto à pergunta "qual nível de isolamento deve ser usado", quanto mais seus dados forem de vital importância para alguém, em algum lugar, mais será o caso de Serializable ser sua única opção razoável.

Erwin Smout
fonte
0

Eu acho que há alguma diferença entre leitura não repetível e leitura fantasma.

O Não repetitivo significa que há uma transação de reboque A e B. se B pode notar a modificação de A, então talvez aconteça uma leitura suja, então deixamos B notar a modificação de A após A confirmar.

Há uma nova questão: deixamos B notar a modificação de A após A confirmar, significa A modificar um valor da linha que o B está mantendo; em algum momento B lerá a linha novamente, para que B tenha um novo valor diferente na primeira vez que get, chamamos de Não repetível, para lidar com o problema, deixamos o B lembrar de algo (porque eu ainda não sei o que será lembrado) quando B começar.

Vamos pensar na nova solução, também podemos notar que há um novo problema, porque deixamos B lembrar algo, então o que aconteceu em A, o B não pode ser afetado, mas se B quiser inserir alguns dados na tabela e B verifique a tabela para garantir que não haja registro, mas esses dados foram inseridos por A; talvez ocorra algum erro. Nós chamamos de leitura fantasma.

Han R
fonte
0

leitura não repetível é um nível de isolamento e leitura fantasma (leitura do valor confirmado por outras transações) é um conceito (tipo de leitura, por exemplo, leitura suja ou leitura de instantâneo). O nível de isolamento de leitura não repetível permite leitura fantasma, mas não leituras sujas ou instantâneas.

sn.anurag
fonte