Relação dos níveis de isolamento da transação com os bloqueios na mesa

105

Eu li cerca de 4 níveis de isolamento:

Isolation Level       Dirty Read    Nonrepeatable Read  Phantom Read  
READ UNCOMMITTED      Permitted       Permitted           Permitted
READ COMMITTED              --        Permitted           Permitted
REPEATABLE READ             --             --             Permitted
SERIALIZABLE                --             --              --

Eu quero entender o bloqueio que cada isolamento de transação assume na mesa

READ UNCOMMITTED - no lock on table
READ COMMITTED - lock on committed data
REPEATABLE READ - lock on block of sql(which is selected by using select query)
SERIALIZABLE - lock on full table(on which Select query is fired)

abaixo estão os três fenômenos que podem ocorrer no isolamento da transação
Leitura suja - sem bloqueio
Leitura não repetível - sem leitura suja como bloqueio em dados confirmados
Leitura fantasma - bloqueio no bloco de sql (que é selecionado usando a consulta selecionada)

Quero entender onde definimos esses níveis de isolamento: apenas no nível jdbc / hibernate ou no banco de dados também

PS: Já passei pelos links em níveis de isolamento no oracle , mas eles parecem desajeitados e falam sobre banco de dados específico

Aprendiz
fonte
3
Isso depende completamente do banco de dados. Diferentes bancos de dados podem usar diferentes algoritmos para níveis de isolamento. Alguns podem usar MVCC (sem bloqueios em consultas selecionadas), alguns usam bloqueio estrito de 2 fases (bloqueios compartilhados e exclusivos).
chá brb de

Respostas:

157

Eu quero entender o bloqueio que cada isolamento de transação assume na mesa

Por exemplo, você tem 3 processos simultâneos A, B e C. A inicia uma transação, grava dados e efetua o commit / rollback (dependendo dos resultados). B apenas executa uma SELECTinstrução para ler os dados. C lê e atualiza dados. Todos esses processos funcionam na mesma mesa T.

  • LEIA NÃO COMPROMETIDO - sem bloqueio na mesa. Você pode ler os dados da tabela enquanto escreve nela. Isso significa que A grava dados (não confirmados) e B pode ler esses dados não confirmados e usá-los (para qualquer propósito). Se A executa uma reversão, B ainda leu os dados e os usou. Esta é a maneira mais rápida, mas mais insegura de trabalhar com dados, pois pode levar a furos de dados em tabelas não relacionadas fisicamente (sim, duas tabelas podem ser logicamente, mas não fisicamente relacionadas em aplicativos do mundo real = \).
  • READ COMMITTED - bloqueio de dados confirmados. Você pode ler os dados que foram apenas confirmados. Isso significa que A grava dados e B não pode ler os dados salvos por A até que A execute um commit. O problema aqui é que C pode atualizar os dados que foram lidos e usados ​​no cliente B e B não terá os dados atualizados.
  • READ REPEATABLE - bloqueia em um bloco de SQL (que é selecionado usando a consulta selecionada). Isso significa que B lê os dados sob alguma condição WHERE aField > 10 AND aField < 20, ou seja , A insere dados onde o aFieldvalor está entre 10 e 20, então B lê os dados novamente e obtém um resultado diferente.
  • SERIALIZABLE - bloqueio em uma tabela completa (na qual a consulta Select é acionada). Isso significa que B lê os dados e nenhuma outra transação pode modificar os dados da tabela. Essa é a maneira mais segura, porém mais lenta, de trabalhar com dados. Além disso, uma vez que uma simples operação de leitura bloqueia a tabela , isso pode levar a problemas pesados ​​na produção: imagine que a tabela T é uma tabela de Faturas, o usuário X deseja saber as faturas do dia e o usuário Y deseja criar uma nova fatura, então enquanto X executa a leitura das faturas, Y não consegue adicionar uma nova fatura (e quando se trata de dinheiro, as pessoas ficam muito bravas, principalmente os patrões).

Quero entender onde definimos esses níveis de isolamento: apenas no nível JDBC / hibernação ou no banco de dados também

Usando JDBC, você o define usando Connection#setTransactionIsolation.

Usando o Hibernate:

<property name="hibernate.connection.isolation">2</property>

Onde

  • 1: LEIA NÃO COMPROMETIDO
  • 2: LEIA COMPROMETIDO
  • 4: READ READ
  • 8: SERIALIZÁVEL

A configuração do Hibernate é obtida daqui (desculpe, está em espanhol).

A propósito, você também pode definir o nível de isolamento no RDBMS:

e assim por diante...

Luiggi Mendoza
fonte
docs.oracle.com/cd/B12037_01/server.101/b10743/consist.htm Apenas para adicionar para Oracle: Pode-se definir o nível de isolamento de uma transação usando uma dessas instruções no início de uma transação: SET TRANSACTION ISOLATION LEVEL LEVEL COMMITTED; DEFINIR O NÍVEL DE ISOLAMENTO DA TRANSAÇÃO SERIALIZÁVEL; CONFIGURAR SOMENTE LEITURA DA TRANSAÇÃO;
Aluno
2
Além disso, para economizar o custo de rede e processamento de iniciar cada transação com uma instrução SET TRANSACTION, você pode usar a instrução ALTER SESSION para definir o nível de isolamento da transação para todas as transações subsequentes: ALTER SESSION SET ISOLATION_LEVEL SERIALIZABLE; ALTER SESSION SET ISOLATION_LEVEL READ COMMITTED;
Aluno de
12
Com relação ao READ REPEATABLE - acho que um exemplo melhor para demonstrar isso é o seguinte: B inicia uma transação, lê os dados no bloco do sql WHERE aField> 10 AND aField <20, esses dados ficam bloqueados até a transação terminar. A tenta atualizar esses dados, mas espera por causa do bloqueio. Agora, quando B ler esses dados novamente na mesma transação, é garantido que os mesmos dados sejam lidos, porque está bloqueado. Corrija-me se eu estiver errado.
BornToCode
1
@LuiggiMendoza Como conceito geral, os níveis de isolamento são apenas leitura suja , leitura não repetível e linhas fantasmas . Locks (S2PL) ou MVCC são implementações para diferentes fornecedores.
chá brb de
4
@LuiggiMendoza - Não fui preciso, deveria ser assim - os dados que B lê não são alterados, mas as seleções consequentes feitas por B podem retornar mais linhas. Isso porque A não pode modificar as linhas que B já leu , até que A as libere. No entanto, A pode inserir novas linhas que qualificam a condição where (e, portanto, da próxima vez que A executar um select, obterá um resultado diferente com mais linhas - uma leitura fantasma).
BornToCode
9

Como diz o brb tea, depende da implementação do banco de dados e do algoritmo que eles usam: MVCC ou Two Phase Locking.

CUBRID (RDBMS de código aberto) explica a ideia desses dois algoritmos:

  • Bloqueio de duas fases (2PL)

A primeira é quando a transação T2 tenta alterar o registro A, ela sabe que a transação T1 já alterou o registro A e espera até que a transação T1 seja concluída porque a transação T2 não pode saber se a transação T1 será confirmada ou rolada costas. Este método é chamado de bloqueio de duas fases (2PL).

  • Controle de simultaneidade de várias versões (MVCC)

A outra é permitir que cada uma delas, transações T1 e T2, tenham suas próprias versões alteradas. Mesmo quando a transação T1 mudou o registro A de 1 para 2, a transação T1 deixa o valor original 1 como está e escreve que a versão da transação T1 do registro A é 2. Então, a seguinte transação T2 altera o registro A de 1 a 3, não de 2 a 4, e escreve que a versão da transação T2 do registro A é 3.

Quando a transação T1 é revertida, não importa se o 2, a versão da transação T1, não é aplicado ao registro A. Depois disso, se a transação T2 for confirmada, o 3, a versão da transação T2, será aplicado ao registro A. Se a transação T1 for confirmada antes da transação T2, o registro A será alterado para 2 e, em seguida, para 3 no momento da confirmação da transação T2. O status final do banco de dados é idêntico ao status de execução de cada transação independentemente, sem qualquer impacto nas outras transações. Portanto, ele satisfaz a propriedade ACID. Esse método é chamado de controle de simultaneidade de várias versões (MVCC).

O MVCC permite modificações simultâneas ao custo de aumento da sobrecarga na memória (porque tem que manter versões diferentes dos mesmos dados) e computação (no nível REPETEABLE_READ você não pode perder atualizações, então deve verificar as versões dos dados, como Hiberate faz com o Optimistick Locking ).

Em 2PL Transaction, os níveis de isolamento controlam o seguinte :

  • Se bloqueios são executados quando os dados são lidos e que tipo de bloqueios são solicitados.

  • Por quanto tempo os bloqueios de leitura são mantidos.

  • Se uma operação de leitura faz referência a linhas modificadas por outra transação:

    • Bloqueie até que o bloqueio exclusivo na linha seja liberado.

    • Recupere a versão confirmada da linha que existia no momento em que a instrução ou transação foi iniciada.

    • Leia a modificação de dados não confirmada.

A escolha de um nível de isolamento de transação não afeta os bloqueios adquiridos para proteger as modificações de dados. Uma transação sempre obtém um bloqueio exclusivo em todos os dados que modifica e mantém esse bloqueio até que a transação seja concluída, independentemente do nível de isolamento definido para essa transação. Para operações de leitura, os níveis de isolamento da transação definem principalmente o nível de proteção contra os efeitos das modificações feitas por outras transações.

Um nível de isolamento mais baixo aumenta a capacidade de muitos usuários de acessar dados ao mesmo tempo, mas aumenta o número de efeitos de simultaneidade , como leituras sujas ou atualizações perdidas, que os usuários podem encontrar.

Exemplos concretos da relação entre bloqueios e níveis de isolamento no SQL Server (use 2PL, exceto em READ_COMMITED com READ_COMMITTED_SNAPSHOT = ON)

  • READ_UNCOMMITED: não emite bloqueios compartilhados para evitar que outras transações modifiquem os dados lidos pela transação atual. As transações READ UNCOMMITTED também não são bloqueadas por bloqueios exclusivos que impediriam a transação atual de ler linhas que foram modificadas, mas não confirmadas por outras transações. [...]

  • READ_COMMITED:

    • Se READ_COMMITTED_SNAPSHOT estiver definido como OFF (o padrão): usa bloqueios compartilhados para evitar que outras transações modifiquem as linhas enquanto a transação atual está executando uma operação de leitura. Os bloqueios compartilhados também bloqueiam a instrução de ler linhas modificadas por outras transações até que a outra transação seja concluída. Os bloqueios de linha são liberados antes que a próxima linha seja processada. [...]
    • Se READ_COMMITTED_SNAPSHOT estiver definido como ON, o Mecanismo de Banco de Dados usará o controle de versão de linha para apresentar a cada instrução um instantâneo consistente transacional dos dados conforme existiam no início da instrução. Os bloqueios não são usados ​​para proteger os dados de atualizações por outras transações.
  • REPETEABLE_READ: bloqueios compartilhados são colocados em todos os dados lidos por cada instrução na transação e são mantidos até que a transação seja concluída.

  • SERIALIZABLE: Os bloqueios de intervalo são colocados no intervalo de valores-chave que correspondem às condições de pesquisa de cada instrução executada em uma transação. [...] Os bloqueios de intervalo são mantidos até que a transação seja concluída.

gabrielgiussi
fonte
5

Os bloqueios são sempre feitos no nível do banco de dados: -

Documento oficial da Oracle: - Para evitar conflitos durante uma transação, um SGBD utiliza travas, mecanismos para bloquear o acesso de terceiros aos dados que estão sendo acessados ​​pela transação. (Observe que no modo auto-commit, onde cada instrução é uma transação, os bloqueios são mantidos para apenas uma instrução.) Depois que um bloqueio é definido, ele permanece em vigor até que a transação seja confirmada ou revertida. Por exemplo, um DBMS pode bloquear uma linha de uma tabela até que as atualizações tenham sido confirmadas. O efeito desse bloqueio seria impedir que um usuário obtivesse uma leitura incorreta, ou seja, lendo um valor antes que ele se tornasse permanente. (Acessar um valor atualizado que não foi confirmado é considerado uma leitura suja porque é possível que esse valor seja revertido para seu valor anterior. Se você leu um valor que é revertido posteriormente, você leu um valor inválido. )

O modo como os bloqueios são configurados é determinado pelo que é chamado de nível de isolamento de transação, que pode variar de nenhuma transação de suporte a transações de suporte que impõem regras de acesso muito rígidas.

Um exemplo de nível de isolamento de transação é TRANSACTION_READ_COMMITTED, que não permitirá que um valor seja acessado antes de ser confirmado. Em outras palavras, se o nível de isolamento da transação for definido como TRANSACTION_READ_COMMITTED, o DBMS não permitirá que ocorram leituras sujas. A interface Connection inclui cinco valores que representam os níveis de isolamento da transação que você pode usar no JDBC.

Goyal Vicky
fonte