Transações e mecanismos para seu controle

Transações


Uma transação é uma sequência de operações em dados que têm um começo e um fim.


Uma transação é uma operação sequencial de leitura e gravação. O final de uma transação pode ser salvar alterações (confirmar, confirmar) ou cancelar alterações (reversão, reversão). Em relação ao banco de dados, uma transação é uma série de consultas, que são tratadas como uma única consulta.

As transações devem satisfazer as propriedades ACID


Atomicidade. Uma transação é totalmente executada ou não é executada.

Coerência. No final da transação, as restrições impostas aos dados (por exemplo, restrições no banco de dados) não devem ser violadas. A consistência implica que o sistema será transferido de um estado correto para outro correto.

Isolamento. As transações executadas simultaneamente não devem se afetar, por exemplo, alterar dados usados ​​por outra transação. O resultado de transações paralelas deve ser como se as transações fossem executadas seqüencialmente.

Sustentabilidade. Uma vez confirmadas, as alterações não devem ser perdidas.

Log de transação


O log armazena as alterações feitas pelas transações, garante atomicidade e estabilidade dos dados em caso de falha do sistema


O log contém os valores que os dados tinham antes e depois da alteração pela transação. A estratégia de log write-ahead exige que você adicione ao log um registro dos valores anteriores antes do início e sobre os valores finais após a conclusão da transação. No caso de uma parada repentina do sistema, o banco de dados lê o log na ordem inversa e descarta as alterações feitas pelas transações. Após encontrar uma transação interrompida, o banco de dados a executa e faz alterações sobre ela no log. Estando no estado no momento da falha, o banco de dados lê o log na ordem direta e retorna as alterações feitas pelas transações. Assim, a estabilidade das transações que já foram confirmadas e a atomicidade da transação interrompida são preservadas.

Simplesmente reexecutar transações erradas não é suficiente para recuperar.

Um exemplo O usuário tem US $ 500 na conta e decide retirá-los por meio de um caixa eletrônico. Duas transações são realizadas. O primeiro lê o valor do saldo e, se houver fundos suficientes no saldo, ele dá dinheiro ao usuário. O segundo subtrai a quantia necessária do saldo. Suponha que um sistema trava e a primeira operação falha e a segunda falha. Nesse caso, não podemos reemitir dinheiro para o usuário sem retornar o sistema ao seu estado original com um saldo positivo.

Níveis de isolamento


Leitura confirmada


O problema com uma leitura suja é que uma transação pode ler o resultado intermediário de outra transação.

Um exemplo O valor inicial do saldo é $ 0. T1 adiciona US $ 50 ao saldo. T2 lê o valor do saldo (US $ 50). T1 cancela as alterações e termina. T2 continua a execução com dados de saldo incorretos.

A solução é Read Committed, que proíbe a leitura de dados modificados por uma transação. Se a transação A alterou algum conjunto de dados, a transação B, ao acessar esses dados, é forçada a aguardar a transação A.

Leitura Repetível


O problema de alterações perdidas (atualizações perdidas). T1 salva alterações sobre alterações em T2.

Um exemplo O valor inicial do saldo é $ 0 e duas transações reabastecem o saldo simultaneamente. T1 e T2 leem um saldo de US $ 0. Em seguida, o T2 adiciona US $ 200 a US $ 0 e salva o resultado. T1 adiciona US $ 100 a US $ 0 e salva o resultado. O resultado total é $ 100 em vez de $ 300.

Problema de leitura irrepetível. A leitura repetida dos mesmos dados retorna valores diferentes.

Um exemplo T1 lê um valor de saldo de $ 0. Em seguida, T2 adiciona US $ 50 ao saldo e termina. T1 lê os dados novamente e detecta uma discrepância com o resultado anterior.

Leitura repetida garante que a leitura repetida retorne o mesmo resultado. Os dados lidos por uma transação são proibidos de serem alterados em outras até que a transação seja concluída. Se a transação A leu algum conjunto de dados, a transação B, ao acessar esses dados, é forçada a aguardar a transação A.

Leitura em ordem (serializável)


Leituras fantasmas Duas consultas que selecionam dados por alguma condição retornam valores diferentes.

Um exemplo T1 solicita o número de todos os usuários cujo saldo é maior que $ 0, mas menor que $ 100. T2 subtrai US $ 1 de um usuário com um saldo de US $ 101. T1 re-executa a solicitação.

Leitura ordenada (serializável). As transações são realizadas como completamente sequenciais. É proibido atualizar e adicionar registros sujeitos às condições da solicitação. Se a transação A solicitar dados da tabela inteira, a tabela inteira será congelada pelo restante das transações até a transação A.

Programador


Define a ordem em que as operações devem ser executadas em transações paralelas


Fornece um nível especificado de isolamento. Se o resultado das operações não depender de sua ordem, essas operações serão comutáveis ​​(permutáveis). Os comandos são lidos e operações em dados diferentes. As operações de leitura e gravação e gravação e gravação não são comutativas. A tarefa do planejador é alternar operações executadas por transações paralelas, para que o resultado da execução seja equivalente à execução seqüencial de transações.

Mecanismos de Controle de Concorrência


Otimista com base na detecção e resolução de conflitos, pessimista com base na prevenção de conflitos


Com uma abordagem otimista, vários usuários têm à disposição cópias dos dados. O primeiro que concluiu a edição salva as alterações, o restante deve mesclar as alterações. Um algoritmo otimista permite que um conflito ocorra, mas o sistema deve se recuperar do conflito.

Com uma abordagem pessimista, o primeiro usuário a capturar dados impede que outros recebam dados. Se os conflitos são raros, é aconselhável escolher uma estratégia otimista, pois fornece um nível mais alto de paralelismo.

Travamento


Se uma transação tiver bloqueado os dados, o restante da transação deverá acessar os dados ao acessá-los.


Um bloco pode ser sobreposto a um banco de dados, tabela, linha ou atributo. O bloqueio compartilhado (bloqueio compartilhado) pode ser imposto aos mesmos dados por várias transações, permite a leitura de todas as transações (incluindo a imposta), proíbe alterações e captura exclusiva. O bloqueio exclusivo pode ser imposto por apenas uma transação, permite qualquer ação da transação imposta, proíbe qualquer ação pelo restante.

Um impasse é uma situação em que as transações estão no modo de espera, com duração indefinida


Um exemplo A primeira transação está aguardando a liberação dos dados capturados pelo segundo, enquanto a segunda está aguardando a liberação dos dados capturados pelo primeiro.

Uma solução otimista para o problema de conflito permite que um conflito ocorra, mas depois restaura o sistema revertendo uma das transações envolvidas no conflito.


Com uma certa frequência, é realizada uma busca por deadlocks. Um dos métodos de detecção é a tempo, ou seja, considerar que ocorreu um conflito se a transação demorar muito. Quando um impasse é encontrado, uma das transações é revertida, o que permite que outras transações envolvidas no impasse sejam concluídas. A escolha da vítima pode basear-se no valor das transações ou na sua antiguidade (esquemas de espera e morte e espera por feridas).

A cada transação T é atribuído um TS com registro de data e hora que contém a hora de início da transação.

Wait-Die

Se TS (Ti) < TS (Tj) , o Ti espera, caso contrário, o Ti reverte e inicia novamente com o mesmo carimbo de hora.

Se uma transação jovem capturou um recurso e uma mais antiga está solicitando o mesmo recurso, é permitido esperar uma transação mais antiga. Se uma transação mais antiga capturou um recurso, uma transação jovem solicitando esse recurso será revertida.

Espere ferida.

Se TS (Ti) < TS (Tj) , então Tj reverte e inicia novamente com o mesmo carimbo de hora, caso contrário, Ti espera.

Se uma transação mais jovem capturou um recurso e uma transação mais antiga está solicitando o mesmo recurso, a transação jovem será revertida. Se uma transação mais antiga capturou o recurso, uma transação mais nova que solicita esse recurso pode esperar. A seleção da vítima com base na antiguidade impede conflitos, mas reverte as transações que não estão em um estado de bloqueio. O problema é que as transações podem ser revertidas muitas vezes porque Uma transação mais antiga pode reter um recurso por um longo tempo.

Uma solução pessimista para o problema de deadlocks não permite que a transação inicie a execução se houver risco de deadlock


Para detectar conflitos, um gráfico é construído (um gráfico de espera, espera por gráfico), cujos vértices são transações e as arestas são direcionadas a partir de transações que aguardam a liberação de dados para a transação que capturou esses dados. Acredita-se que ocorreu um conflito se o gráfico estiver em loop. Construir um gráfico de espera, especialmente em bancos de dados distribuídos, é um procedimento caro.

Bloqueio de duas fases - impedindo conflitos, capturando todos os recursos utilizados pela transação no início da transação e liberando-os no final


Todas as operações de bloqueio devem preceder o primeiro desbloqueio. Possui duas fases - a fase de crescimento, na qual ocorre a captura das garras e a fase de encolhimento, na qual ocorre a liberação das garras. Se for impossível capturar um dos recursos, a transação começará novamente. É possível que uma transação não possa capturar os recursos necessários, por exemplo, se várias transações competem pelos mesmos recursos.

A confirmação em duas fases garante que a confirmação seja executada em todas as réplicas do banco de dados


Cada banco de dados contribui com informações sobre os dados que serão alterados para o log e correspondem ao coordenador OK (fase de votação). Depois que todos responderam bem, o coordenador envia um sinal obrigando todos a se comprometerem. Após confirmar o servidor, eles respondem bem, se pelo menos um não respondeu, então o coordenador envia um sinal para cancelar as alterações em todos os servidores (fase de conclusão).

Método de carimbo de data e hora


Uma transação mais antiga reverte ao tentar acessar os dados envolvidos em uma transação mais nova


Cada transação recebe um carimbo de data / hora TS correspondente ao horário de início da execução. Se Ti for mais antigo que Tj , então TS (Ti) < TS (Tj) .

Quando uma transação é revertida, é atribuído um novo carimbo de data / hora. Cada objeto de dados Q envolvido na transação é marcado com dois rótulos. W-TS (Q) é o registro de data e hora da transação mais jovem que foi gravada com êxito em Q. R-TS (Q) é o registro de data e hora da transação mais jovem que concluiu um registro de leitura sobre Q.

Quando a transação T solicita a leitura de dados Q , duas opções são possíveis.

Se TS (T) < W-TS (Q) , ou seja, os dados foram atualizados por uma transação mais nova, a transação T reverte.

Se TS (T) > = W-TS (Q) , a leitura é realizada e R-TS (Q) se torna MAX (R-TS (Q), TS (T)) .

Quando a transação T solicita uma alteração nos dados Q , duas opções são possíveis.

Se TS (T) < R-TS (Q) , ou seja, os dados já tiverem sido lidos por uma transação mais nova e se uma alteração for feita, surgirá um conflito. A transação T reverte.

Se TS (T) < W-TS (Q) , ou seja, a transação tentar substituir o valor mais recente, a transação T reverte. Noutros casos, a alteração é realizada e W-TS (Q) torna-se igual a TS (T) .

Não é necessária nenhuma construção cara de gráfico caro. As transações mais antigas dependem das mais recentes; portanto, não há loops na coluna de espera. Não há impasses, porque as transações não esperam, mas são revertidas imediatamente. Recompensas em cascata são possíveis. Se o Ti retrocedeu e Tj leu os dados que o Ti alterou, o Tj também deve retroceder. Se, ao mesmo tempo, Tj já tiver sido comunicado, haverá uma violação do princípio da estabilidade.

Uma solução para reversões em cascata. Uma transação executa todas as operações de gravação no final, e as transações restantes devem aguardar a conclusão desta operação. As transações estão aguardando uma confirmação antes da leitura.

Regra de gravação Thomas - uma variação do método de carimbo de data e hora em que os dados atualizados por uma transação mais nova não podem ser substituídos por uma mais antiga


A transação T solicita uma alteração nos dados Q. Se TS (T) < W-TS (Q) , ou seja, a transação está tentando substituir um valor mais recente, a transação T não é revertida como no método de carimbo de data / hora.

Source: https://habr.com/ru/post/pt446662/


All Articles