Eu sei que essa provavelmente é uma pergunta boba, É a minha primeira, Parece tão fundamental que não consigo encontrar a resposta em lugar nenhum, porque deve ser tão simples que ninguém explicou. Quero entender completamente como as transações funcionam e, em particular, os níveis de isolamento e, especialmente, o nível de isolamento UNCOMMITTED READ e dirty read.
Há algumas informações contraditórias. Todos esses links abaixo são da documentação oficial:
Li muitos recursos online, alguns destes: https://learn.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-ver16
https://medium.com/inspiredbrilliance/what-are-database-locks-1aff9117c290
https://docs.oracle.com/cd/E17277_02/html/TransactionGettingStarted/isolation.html#dirtyreads
diga algo como:
Uma leitura suja ocorre quando uma transação pode visualizar dados modificados por outra transação que ainda não foi confirmada. Mas como isso é possível e o que isso significa exatamente?
Mas isso é contraditório, se eu ver a documentação do PostgreSQL aqui: https://www.postgresql.org/docs/current/tutorial-transactions.html
Diz:
Transações são um conceito fundamental de todos os sistemas de banco de dados. O ponto essencial de uma transação é que ela agrupa várias etapas em uma única operação do tipo tudo ou nada. Os estados intermediários entre as etapas não são visíveis para outras transações simultâneas e, se ocorrer alguma falha que impeça a transação de ser concluída, nenhuma das etapas afetará o banco de dados.
E aqui:
Outra propriedade importante dos bancos de dados transacionais está intimamente relacionada à noção de atualizações atômicas: quando várias transações estão sendo executadas simultaneamente, cada uma não deve ser capaz de ver as alterações incompletas feitas por outras. Por exemplo, se uma transação estiver ocupada totalizando todos os saldos das agências, não seria bom incluir o débito da agência de Alice, mas não o crédito da agência de Bob, nem vice-versa. Portanto, as transações devem ser tudo ou nada, não apenas em termos de seu efeito permanente no banco de dados, mas também em termos de sua visibilidade à medida que acontecem. As atualizações feitas até agora por uma transação aberta são invisíveis para outras transações até que a transação seja concluída, quando todas as atualizações se tornam visíveis simultaneamente.
Eu pensei que as transações são autônomas e tudo ou nada, então como uma instrução de atualização, por exemplo, no meio de uma transação antes do commit, pode ser visível para outra? Afinal, duas ou mais transações podem até ter seus próprios threads/processos no caso do PostgreSQL, então como elas podem visualizar os dados antes do commit?
Isso significa que quando executamos instruções DML individuais dentro de uma transação, elas atualizam as linhas antes do commit e então revertem se falharem? Isso depende de como os bloqueios? Porque essa é a única maneira que eu consigo pensar que poderia funcionar
No que diz respeito às leituras sujas, uma leitura suja é o valor na linha original que foi selecionado por outra transação que pode modificá-la ou são os dados dentro de uma transação que foram atualizados, mas ainda não confirmados.
Não estou entendendo nada muito fundamental sobre isso
Por exemplo:
Considere esta tabela de exemplo básica:
CREATE TABLE TransactionEg (
id INT GENERATED BY DEFAULT AS IDENTITY,
name VARCHAR,
x INT,
y INT,
CONSTRAINT TransactionEgPk PRIMARY KEY(id)
);
INSERT INTO transactioneg (name, x, y)
VALUES
('Row 1', 5, 11),
('Row 2', 7, 23),
('Row 3', 11, 36);
Se transação 1:
BEGIN;
SELECT * FROM transactioneg T WHERE T.id = 1;
UPDATE transactioneg T SET x = x + 5 WHERE T.id = 1;
COMMIT;
Mais ou menos no mesmo momento ou logo após a instrução SELECT na 1ª transação, transação 2:
BEGIN;
SELECT * FROM transactioneg T WHERE T.id = 1;
UPDATE transactioneg T SET x = x + 10 WHERE T.id = 1;
COMMIT;
A transação 1 atualizaria o valor de x de 5 para 10. Então a transação 2 vê 10 antes do Commit? Ou ela só obtém 5, já que esse é o valor original antes do commit e o 5 se torna a leitura suja?
Qualquer conselho seria bem-vindo, embora eu ache que posso receber votos negativos por essa pergunta, espero que não.
Infelizmente, você está percebendo a discrepância entre os objetivos ideais de um sistema de controle de transações, que é facilitar o isolamento total de transações simultâneas umas das outras, e a realidade prática de como os mecanismos de banco de dados SQL tradicionais e o hardware de suporte são geralmente projetados para funcionar, e os recursos que os mecanismos precisam para ter um bom desempenho em uso normal, para ter um desempenho adequado em circunstâncias degradadas e para serem supervisionados adequadamente.
O
READ UNCOMMITTED
nível de isolamento é amplamente considerado como não tendo uso legítimo na operação normal de um aplicativo de banco de dados bem projetado.Ele é usado por dois motivos. Um é quando se lida com uma adaptação para (ou consulta ad-hoc de) um aplicativo existente cujo design existente impede o uso de níveis de isolamento mais altos por motivos de desempenho, e é considerado mais importante que a nova consulta seja executada na velocidade mais alta possível e com a menor perspectiva de interferência na progressão de outras transações, do que que os resultados da transação unisolada sejam teoricamente livres de defeitos.
Um programador com profundo entendimento de uma aplicação específica pode ser capaz de raciocinar manualmente quais defeitos podem ocorrer nas circunstâncias e com que frequência, e aceitá-los como toleráveis para o propósito. Isso pode ocorrer quando os dados informam decisões regulares que são individualmente de baixo risco e podem, às vezes, estar erradas.
Mais frequentemente, esse modo é (mal)utilizado excessivamente por desenvolvedores incompetentes para resolver grosseiramente problemas de desempenho em aplicativos de banco de dados (normalmente problemas criados por seu próprio trabalho), que normalmente poderiam ser resolvidos de forma diferente com quantidades modestas de trabalho de design comum e competências padrão.
Outro motivo para usar esse modo de isolamento é quando algum tipo de ação de supervisão está ocorrendo e esse supervisor deseja anular completamente o isolamento oferecido pelo gerenciador de transações (por exemplo, isso pode ser para inspecionar o progresso de outras transações simultâneas que estão sendo executadas sob garantias de isolamento mais fortes).
Para entender tudo isso corretamente, meu conselho seria estar preparado para uma quantidade considerável de complexidade, pois todos os detalhes não se reduzem a respostas simples, e os detalhes podem diferir entre marcas de mecanismos SQL e entre diferentes modos operacionais que esses mecanismos fornecem.
A maioria dos profissionais dessa área aceita que a situação não é boa do ponto de vista teórico ou de questões de ensino.
Uma leitura suja seria ver dados não confirmados:
Se a transação dois vir a inserção não confirmada, isso seria uma leitura suja.
Diferentes sistemas de gerenciamento de banco de dados implementam os níveis de isolamento do padrão SQL de forma diferente. O padrão SQL define que leituras sujas são “possíveis” no
READ UNCOMMITTED
nível de isolamento, mas não diz que você tem garantia de obter leituras sujas. O PostgreSQL usa essa brecha e “atualiza” você paraREAD COMMITTED
quando você solicitaREAD UNCOMMITTED
.Isso não é um problema, porque ninguém realmente quer ver dados sujos. Os sistemas de gerenciamento de banco de dados que permitem que você veja dados sujos fazem isso porque eles estão usando bloqueios de leitura , e você precisa
READ UNCOMMITTED
evitar tomar esses bloqueios de leitura. Em essência, você está sacrificando consistência por simultaneidade. No PostgreSQL, leitores nunca bloqueiam escritores e vice-versa, para que não haja necessidade de leituras sujas.