Qual é a relação exata entre uma transação do banco de dados e o bloqueio?

16

Esta é uma pergunta humilde feita no espírito de aumentar meu conhecimento; seja gentil em sua resposta.

Como desenvolvedor de aplicativos de longa data, sei em algum nível o que é uma transação (eu os uso o tempo todo). Deixando de lado os níveis de isolamento da transação no momento, em um nível alto, uma transação permite que um bloco de trabalho seja concluído totalmente ou não existe, e permite uma certa quantidade de isolamento de outras atividades de modificação do banco de dados.

Eu também sei o que é (em vários bancos de dados) um bloqueio, ou pelo menos como se comporta (se eu bloquear uma tabela de alguma maneira explicitamente, nenhum outro processo ou thread poderá atualizar nada sobre essa tabela).

O que eu claramente não entendo é: em vários bancos de dados, quando bloqueio explicitamente uma linha ou tabela, estou empregando exatamente as mesmas construções que são usadas pelos recursos de transação do banco de dados sob as cobertas para fazer a transação funcionar corretamente?

Ou seja, me ocorre que, para que uma transação seja atômica e isolada, ela deve estar travando. Esse bloqueio iniciado por transação e oculto por transação é o mesmo tipo de bloqueio que vários bancos de dados me permitem acessar através de construções como comandos SELECT FOR UPDATEexplícitos ou LOCK? Ou esses dois conceitos são completamente diferentes?

Mais uma vez, peço desculpas pela ingenuidade desta questão; Fico feliz em ser apontado para fontes mais fundamentais.

Laird Nelson
fonte

Respostas:

12

quando bloqueio explicitamente uma linha ou tabela, estou empregando exatamente as mesmas construções usadas pelos recursos de transação do banco de dados sob as cobertas para fazer a transação funcionar corretamente?

Sim. Se isso não for verdade, o seu próprio 'bloqueio' terá como escopo apenas outro 'bloqueio' semelhante e não interagirá com o bloqueio do próprio motor. Portanto, você bloquearia uma linha em uma tabela para que não possa ser bloqueada por outro aplicativo da mesma maneira, mas sua trava será ignorada pelo próprio mecanismo. Essa semântica raramente é desejada. Na maioria das vezes, um aplicativo bloqueando uma linha significa 'bloqueá-lo contra qualquer meio de acesso / modificação'. Nota lateral que mecanismos de bloqueio que são estritamente aplicação específica fazer existe, porque eles são úteis. Por exemplo, o SQL Server possui bloqueios de aplicativos .

me ocorre que, para que uma transação seja atômica e isolada, ela deve estar travando.

O bloqueio é um meio de conseguir isso. A principal alternativa é o controle de versão. Atualmente, a maioria dos bancos de dados suporta os dois (o que também significa que, se você 'bloquear' uma linha no aplicativo, mas outra transação usar o controle de versão para ler a linha, ela será lida porque seu bloqueio não bloqueia leituras com versão).

Você está circulando em torno de um conceito conhecido no mundo de implementação de banco de dados como 'protocolo de bloqueio de duas fases' . o artigo vinculado da Wikipedia é um bom começo. Se você quiser ler uma explicação mais detalhada sobre este tópico, recomendo ir à biblioteca e solicitar um empréstimo no Transaction Processing: Concepts and Techniques . Praticamente todos os bancos de dados existentes são, em essência, uma implementação desse livro.

Remus Rusanu
fonte
Talvez você pode adicionar sobre a (sem bloqueio) controle de concorrência otimista
ypercubeᵀᴹ
Aha! Agora estamos a falar. De fato, espreitando no fundo da minha mente estava o MVCC . Obrigado pela resposta bem articulada, pelas ótimas referências e por dedicar algum tempo para realmente cavar minha pergunta.
Laird Nelson
3

Alguns antecedentes antes de responder às suas perguntas:

Nota: Isso está relacionado ao Microsoft SQL Server - RDBMS ........

  • Em termos muito simples, uma transação é uma sequência de trabalho que deve ser executada como uma única unidade lógica na sua totalidade e deve manter as propriedades ACID.
  • Qualquer RDBMS deve fornecer "recursos de bloqueio" que possam ser usados ​​para concluir a transação na íntegra, preservando o isolamento da transação e sua durabilidade. Isso garante a integridade física do banco de dados.
  • Mais importante, por padrão - as transações são gerenciadas no nível da conexão. Portanto, quando uma transação é iniciada em uma conexão, todas as instruções T-SQL (S / I / U / D) executadas nessa conexão fazem parte da transação até o término da transação. ( MARS é tratado de maneira diferente)

Agora, de volta às suas perguntas:

quando bloqueio explicitamente uma linha ou tabela, estou empregando exatamente as mesmas construções usadas pelos recursos de transação do banco de dados sob as cobertas para fazer a transação funcionar corretamente?

Sim. Isso significa que você deve ter cuidado ao determinar a sequência de dados que serão modificados e que deixarão o banco de dados em um estado consistente. Em outras palavras, sua operação DML deve deixar o banco de dados em um estado consistente, limitado às regras de negócios da sua organização. Ainda, o RDBMS (aqui SQL Server) pode impor a integridade física da transação.

No BOL: o bloqueio e o controle de versão de linha impedem que os usuários leiam dados não confirmados e impedem que vários usuários tentem alterar os mesmos dados ao mesmo tempo. Sem bloqueio ou controle de versão de linha, as consultas executadas nesses dados podem produzir resultados inesperados retornando dados que ainda não foram confirmados no banco de dados.

Esse bloqueio iniciado por transação, oculto por transação, é o mesmo tipo de bloqueio que vários bancos de dados me permitem acessar através de construções como SELECT FOR UPDATE ou comandos explícitos LOCK?

Tudo no servidor sql está contido em uma transação. Quando você acessa seus dados, o RDBMS precisa bloquear, dependendo do nível de isolamento e das Operações que você está executando nos seus dados. Verifique esta resposta para mais detalhes.

Algumas boas referências:

Kin Shah
fonte
2

Eu diria que as transações fazem parte da "interface" do banco de dados, em certo sentido, é que você, como desenvolvedor, decide quando começar, terminar, o que fazer no escopo das transações, etc. Bloqueios, a meu ver, pertencem aos detalhes da implementação e usado para sincronizar o acesso a diferentes objetos. Na maioria dos casos, o próprio mecanismo decide o que e por quanto tempo deve ser bloqueado. Existem muitos bloqueios no nível do sistema que não podem ser manipulados diretamente (por exemplo, o mecanismo pode bloquear determinadas áreas da memória). Mesmo quando se trata de bloqueios de DML, muitos deles acontecem nos bastidores (por exemplo, para garantir a integridade referencial do Oracle e, tanto quanto me lembro, o SQLServer pode colocar um bloqueio em uma linha correspondente na tabela mestre se um novo registro for inserido detalhes) como resultado de instruções DML emitidas na transação.

Quando se trata de transações, você pode esperar um comportamento mais ou menos consistente de qualquer RDMS que alega conformidade com SQL e suporte a transações, mas quando se trata de bloqueios, quase todos os fornecedores usam estratégias e terminologias diferentes. A parte comum em todo o RMDS, até onde posso dizer, é que a simultaneidade entre transações é definida pelo nível de isolamento, enquanto a simultaneidade entre bloqueios é controlada por tipos de bloqueio (compartilhado, exclusivo, etc.).

Para resumir, os bloqueios são um mecanismo de baixo nível para controlar a consistência dos objetos e a simultaneidade. Bloqueios podem ser emitidos durante a execução de instruções SQL. Depende da implementação do nível de isolamento da transação, o mecanismo pode colocar diferentes tipos de bloqueios nos objetos afetados (linhas, grupo de linhas, índices, etc.). Há um número limitado de comandos disponíveis para emitir bloqueios manualmente ( SELECT FOR UPDATE, LOCK). Bloqueios DML podem ser escalados (depende do RDMS, por exemplo, em SQLServer linha-> página-> partição-> tabela). Bloqueios também podem ser emitidos pelo mecanismo de banco de dados durante o início da conexão, backups, restauração, procedimento / gatilho / função / etc, recompilação, inicialização, desligamentos etc.

Não tenho certeza se isso responde à sua pergunta, mas espero que faça sentido.

a1ex07
fonte
Obrigado pelo seu comentário. Você é definitivamente o mais próximo até agora. Ainda estou tentando ver se as transações são sempre implementadas em termos dos bloqueios usados ​​por, digamos, explícitos LOCKou SELECT FOR UPDATEinstruções ou por meio de outro mecanismo.
Laird Nelson
Tanto quanto eu sei, em BEGIN TRANSACTIONsi não emite bloqueios. Os bloqueios aparecerão após os DMLs dentro da transação.
a1ex07
Esclarecimento - eu quis dizer que BEGIN TRANSACTIONele próprio não cria bloqueios DML; deve em questão fato de alguns bloqueios internos porque tem que alocar recursos, adicionar uma entrada à tabela de sistema [s] (se houver) que contém transações ativas, etc.
a1ex07
1

Usarei o jargão do SQL Server, mas os conceitos devem ser os mesmos para outros fornecedores:

Todo comando que você executa é executado dentro de uma transação. Essa transação pode ser aberta explicitamente com BEGIN TRAN, ou implicitamente, pelo mecanismo de banco de dados. A razão pela qual uma transação implícita é aberta é que o mecanismo ainda precisa manter a conformidade com o ACID e a capacidade de reversão.

Quando você faz um SELECT FOR UPDATE, isso significa que, enquanto a transação estiver em vigor, ela manterá um determinado bloqueio.

Matan Yungman
fonte
Obrigado pelo seu comentário. Isso eu sei. Mas minha pergunta ainda é: quando essa transação é aberta, seu isolamento é realizado mantendo seus próprios bloqueios? Em caso afirmativo, esses bloqueios são os mesmos tipos de bloqueios que posso adquirir explicitamente? Ou a transação alcança isolamento por outros meios?
Laird Nelson
2
Sim, este é o mesmo mecanismo. O isolamento é obtido usando bloqueios nos dois modos, os mesmos bloqueios que você pode adquirir explicitamente. A diferença é que, se você não abrir explicitamente uma transação, os bloqueios serão liberados quando o comando for concluído, enquanto em uma transação explícita os bloqueios serão mantidos até você confirmar (não 100% exato por causa dos níveis de isolamento, mas esse é o ideia geral).
Matan Yungman
Obrigado pelo seu comentário. A razão pela qual estou fazendo a minha pergunta é que li em algum lugar que alguns bancos de dados usam o MVCC como meio de obter transações ACID, o que me parece uma maneira livre de bloqueios. Nesses casos, então, não tenho certeza de quando gostaria de emitir um bloqueio explicitamente. Mas essa é provavelmente uma pergunta separada. :-)
Laird Nelson
@LairdNelson que é o nível de isolamento de instantâneo para o SQL Server. Existente, mas não o mecanismo padrão para simultaneidade. É o padrão para Oracle ou Postgresql, IIRC.
Marian
0

Bloqueio são necessários e eles fazem o banco de dados. Isso evita que os dados sejam corrompidos ou invalidados quando vários usuários tentam ler enquanto outros gravam no banco de dados. O isolamento transacional é geralmente implementado bloqueando o que é acessado em uma transação. Aplicativos de design ruim fazem um grande uso do conceito de bloqueio de banco de dados :) !! Portanto, para evitar bloqueios, concentre-se no seu FK e layout de dados.

É tudo sobre o ACID: - leia isto e isso limpará sua mente! ACID é um conjunto de propriedades que você gostaria de aplicar ao modificar um banco de dados.

  • **Atomicidade
  • Consistência
  • Isolamento
  • Durabilidade**

Uma transação é um conjunto de alterações relacionadas que são usadas para obter algumas das propriedades do ACID. Transações são ferramentas para obter as propriedades ACID.

Atomicidade significa que você pode garantir que todas as transações ocorram, ou nenhuma delas; você pode executar operações complexas como uma única unidade, tudo ou nada, e uma falha, falta de energia, erro ou qualquer outra coisa não permitirá que você esteja em um estado em que apenas algumas das mudanças relacionadas ocorreram.

Consistência significa que você garante que seus dados serão consistentes; nenhuma das restrições que você tem sobre dados relacionados será violada.

Isolamento significa que uma transação não pode ler dados de outra transação que ainda não foi concluída. Se duas transações estiverem sendo executadas simultaneamente, cada uma verá o mundo como se estivesse executando sequencialmente e, se uma precisar ler dados gravados por outra, terá que esperar até que a outra termine.

Durabilidade significa que, assim que uma transação é concluída, é garantido que todas as alterações foram registradas em uma mídia durável (como um disco rígido), e o fato de que a transação foi concluída também é registrado.

Portanto, as transações são um mecanismo para garantir essas propriedades; eles são uma maneira de agrupar ações relacionadas de modo que, como um todo, um grupo de operações possa ser atômico, produzir resultados consistentes, ser isolado de outras operações e ser gravado de forma durável.

Up_One
fonte
Obrigado por seu comentário. Eu tenho pelo menos uma noção razoável das propriedades do ACID. O que ainda não estou claro é: as transações implementam o ACID usando os mesmos tipos de bloqueios que posso usar diretamente por meio de LOCKinstruções explícitas , ou o fazem usando algum outro mecanismo?
Laird Nelson
Os bancos de dados oferecem vários níveis de isolamento de transação, que controlam o grau de bloqueio que ocorre ao selecionar dados.Serializável, Leituras repetíveis, Leitura confirmada, Leitura não confirmada.
Up_One