MVCC como uma maneira de garantir o isolamento da transação

Oi Habr. Meu nome é Vladislav Rodin. Atualmente, sou o chefe do curso de arquiteto de carga alta da OTUS e também ensino cursos de arquitetura de software.

Especialmente para o início de um novo conjunto para o curso "Arquiteto de altas cargas" , escrevi um pequeno material, que partilho com prazer.



Introdução


Na última vez, conversamos com você sobre as consequências do enfraquecimento do isolamento de transações nos bancos de dados. Hoje discutiremos mais detalhadamente uma das maneiras de garantir esse isolamento e evitar as anomalias consideradas. Como você deve ter notado, no último artigo duas abordagens foram frequentemente distinguidas: uma foi baseada no fato de os registros terem algumas versões e a segunda no fato de que bloquearemos a gravação de uma maneira ou de outra . Assim, são distinguidas duas classes de bancos de dados: versionado e bloqueador . Hoje falaremos sobre o que são controladores de versão e vamos deixar a consideração dos bloqueadores na próxima vez.

Versionioners


Como eu disse, uma das abordagens é baseada em versionamento. É também chamado de abordagem otimista ou MVCC (controle de simultaneidade multiversão) . De fato, ocorre o armazenamento de versão para transações ativas.

Onde estão armazenadas as versões?


A implementação do mecanismo depende do banco de dados. Vou dar exemplos de alguns deles.

PostgreSQL


Cada transação é caracterizada por algum id-shnik. As transações id-shnik crescem monotonamente. Qualquer linha possui 2 atributos que representam meta-informações para fornecer um mecanismo: updated_by_id - ID da transação que atualizou este registro pela última vez e delete_by_id - ID da transação que excluiu este registro. Quando uma nova transação chega, o banco de dados determina os apelidos de identificação das transações atualmente sendo executadas, as alterações feitas por essas transações serão ignoradas na transação recebida. Acontece que a transação recebida funciona como se estivesse com sua versão dos dados. As versões antigas dos dados são armazenadas no mesmo local que as atuais. Se a atualização chegar, outra linha será adicionada e esse registro se tornará ativo. Também está claro que, para a operação correta desse esquema, é necessário um "coletor de lixo":se algum registro deletou_by_id = 100 e o id-shnik mínimo entre as transações atuais é 150, esse registro deve ser excluído.

MySQL (mecanismo InnoDB)


Somente a versão atual é armazenada no banco de dados MySQL. Quando a atualização chega, os dados dentro do arquivo da tabela são corrigidos. Após o ajuste dos dados, a versão anterior está no log de reversão. Existem vários logs de reversão no MySQL (eles são diferentes para insert'ov e update'ov). Se uma transação precisar de uma versão anterior da linha, o sistema desfará o log e restaurará a versão necessária. A versão também é determinada pelo ID da transação.

Oráculo


O esquema é semelhante ao MySQL: as versões atuais são armazenadas no arquivo de dados, as versões antigas são restauradas graças ao desfazer log. O log de desfazer no Oracle é reescrito ciclicamente. Portanto, uma situação é possível quando uma transação precisa de uma versão muito antiga do registro, mas no log de desfazer ela não está mais lá. Se essa situação ocorrer, a transação falhará.

MS SQL


O MS SQL permite a inclusão dos modos versionador e bloqueador. Para ativar o modo de versão nas configurações do banco de dados, você deve ativar os instantâneos. No MS SQL, há uma tabela do sistema (tempdb), projetada para armazenar tabelas temporárias. É o tempdb usado para armazenar versões antigas, enquanto a tabela contém as versões atuais. O processo do sistema monitora que no tempdb há versões às quais ninguém se refere, elas podem ser excluídas. Se a transação for de longa duração, as versões serão salvas para ela. Tempdb cresce, atinge seu tamanho máximo, o MS SQL aloca um pouco de espaço em disco. Se terminar, as transações com isolamento de captura instantânea não poderão ser executadas. Se esse modo de operação for usado, é necessário monitorar transações longas,porque a reversão dessa transação no tempo pode custar tanto quanto funciona e talvez um pouco mais.

Conflitos


Essa abordagem é chamada de otimista, porque esperamos que não haja conflito se transações paralelas de alteração de dados forem executadas. O que acontece em caso de conflito? Suponha que a transação T1 altere 10.000 registros e a transação T2 altere 1 registro em paralelo. Se acontecer que esse 1 registro seja incluído nesses 10.000, uma das transações será revertida: se T1 for executado primeiro, T2 será revertido, caso contrário, será vice-versa.

Mecanismo de reversão


O mecanismo de reversão de transação nas versões com versão depende da implementação. Por exemplo, no PostgreSQL, uma transação é marcada como evacuada e o vácuo libera espaço em disco. Esse mecanismo é rápido o suficiente. No Oracle, para a reversão, os dados são restaurados a partir do log de desfazer. Nesse caso, o tempo de operação aumenta, no entanto, ainda é muito mais rápido do que nos armários. O MySQL funciona da mesma maneira que o Oracle.

Conclusão


A abordagem otimista é boa porque o escritor não bloqueia o leitor, ele simplesmente lê sua versão dos dados. Portanto, o controle de versão é benéfico se o principal ônus é a leitura, e não a escrita (blog, relatórios e outros casos em que você precisa ler com frequência e muito).



Saiba mais sobre o curso aqui.



All Articles