1 - Transações
Uma transação é uma visão abstrata que o sistema gerenciador de banco de dados tem de um programa de usuário, uma seqüência de leituras e escritas em uma coleção de operações, seqüência de ações elementares que deverão ser executadas como se fossem uma unidade atômica, realizando sem interferência externa uma única ação lógica da aplicação no banco de dados.
A gerência de transações assegura que o banco de dados permaneça em um estado consistente (correto) a despeito de falhas no sistema como quedas de energia e crashes do sistema operacional. A transação, quando executada sozinha sempre deve terminar e deve estar preservada a consistência do banco de dados.
Como os acessos a disco são freqüentes, e relativamente lentos, é importante manter a CPU trabalhando em vários programas usuários concorrentemente.
Um programa de usuário pode executar várias operações sobre os dados recuperados da base de dados, mas o SGBD está preocupado apenas sobre quais dados são lidos/escritos da/para a base de dados.
A execução de uma transação se desenvolve em três fases:
a) Início, quando a gerência de transações gera uma identificação unívoca para a transação.
b)execução: a gerência de transações implementa o plano de execução gerado pelo otimizador.
c) término: a gerência de transações interage com todos os gerenciadores de dados que atualizaram dados conforme especificado pela transação garantindo que todos instalem definitivamente nos bancos de dados locais as atualizações, ou as abandonem
2 - Concorrência em um SGBD
Usuários submetem transações e podem pensar que cada transação é executada sozinha.
A concorrência é aplicada pelo SGBD, que intercala ações (leituras e escritas de objetos do BD) de várias transações.
Cada transação deve deixar a base de dados em um estado consistente se o BD está consistente quando a transação é iniciada.
O SGBD garantirá algumas restrições de integridade, dependendo das restrições de integridade declaradas nos comandos CREATE TABLE.
Além disso, o SGBD não compreende a semântica dos dados (i.e, ele não compreende como o saldo de uma conta bancária é calculado).
Problemas:
Efeito de intercalar transações;
Quedas no sistema.
O controle de concorrência controla as interações através de transações concorrentes visando assegurar a consistência do banco de dados. É aplicada pelo SGBD, que intercala ações de várias transações garantindo as restrições de integridade declaradas nas criação das tabelas. Assim, cada vez que uma transação for invocada deve ser executada por completo ou não ser executada e a execução da transação deve se dar sem a interferência de outras transações que estejam sendo executadas simultaneamente.
Para isso são utilizados métodos de escalonamento, listando as ações de um conjunto de transações, representando uma seqüência de execução que deve conservar a mesma ordem de execução das ações das transações presentes nesse conjunto.
Bloqueios
Protocolo de bloqueio: um objeto deve ser bloqueado antes de ser lido ou atualizado, o bloqueio por si só não é suficiente para garantir serialização. Assim no bloqueio em duas fases uma transação deve bloquear os objetos antes de acessá-los e liberá-los antes de terminar, garantindo a serialização, na ordem em que as transações atingem o ponto em que a transação libera o primeiro objeto de bloqueio (ponto de bloqueio) e não poderá bloquear novos objetos, mas não garante o término, em tal situação, a transação deve ser abortada de reiniciada.
Pré-Ordenação
No protocolo de pré-ordenação uma transação recebe senha única quando começa e ações de uma transação herdam a sua senha a cada nó. As ações de transações distintas são processadas respeitando a ordem das senhas, exceto se comutarem ou se uma ação violar a condição anterior: ela será rejeitada e a transação reiniciada com outra senha. A serialização é garantida, porém a terminação não já que o reinício cíclico de um grupo de transações pode ocorrer, havendo a mesma condição do método anterior.
3 - Propriedades ACID de Transações
Atomicidade: A execução de uma transação deve ser atômica, ou todas as ações são executadas, ou nenhuma é;
Consistência: Cada transação executada isoladamente deve preservar a consistência do banco de dados;
Isolamento: Cada transação deve ser isolada dos efeitos da execução concorrente de outras transações;
Durabilidade: Toda transação que for finalizada de forma bem-sucedida deve persistir seus resultados em banco mesmo na presença de falhas no sistema.
4 - Consistência e Isolamento
É o usuário quem deve garantir a consistência da transação.
Exemplo: Transferência de fundos entre contas não alteram a quantia total de dinheiro nas contas.
O isolamento deve garantir que duas transações, executadas concorrentemente, devem ter o mesmo resultado se executadas em ordem serial.
Exemplo: T1 concorrente com T2 =>T1, T2 ou T2, T1.
5 - Atomicidade de Transações
As falhas em uma transação podem ter como motivo:
Interrupção do SGBD;
Queda do sistema;
Detecção de uma situação inesperada.
Uma transação interrompida ao meio pode deixar o banco de dados em um estado inconsistente.
O banco de dados deve prover recursos para remoção dos efeitos de transações incompletas para garantir a atomicidade.
O SGBD mantém um registro (log) das ações executadas pelo usuário para que estas possam ser desfeitas caso ocorra alguma falha em uma transação.
O log também é utilizado para garantir a durabilidade. Se ocorrer queda do sistema antes que todas as mudanças tenham sido feitas em disco, o log é usado para restaurar o estado do banco de dados quando o sistema for reiniciado.
5 - Escalonamento
Considere duas transações:
T1: BEGIN A=A+100, B=B-100 END
T2: BEGIN A=1.06*A, B=1.06*B END
Intuitivamente, a primeira transação transfere $100 da conta B para a conta A. A segunda acrescenta 6% nas duas contas.
Se as duas são submetidas juntas, não há garantias de que a transação T1 executará antes da transação T2, ou vice-versa.
Entretanto, o efeito final deve ser equivalente ao efeito da execução serial, em alguma ordem, das duas transações.
Um escalonamento é uma lista de ações de um conjunto de transações. Representa uma seqüência de execução que deve conservar a mesma ordem de execução das ações das transações presentes nele.
Exemplo (Continuação)
Considere uma possível intercalação (escalonamento):
T1: A=A+100, B=B-100
T2: A=1.06*A, B=1.06*B
O resultado, para o exemplo acima, está correto. Considere o próximo caso:
T1: A=A+100, B=B-100
T2: A=1.06*A, B=1.06*B
A visão do SGBD para o segundo escalonamento:
T1: R(A), W(A), R(B), W(B)
T2: R(A), W(A), R(B), W(B)
6 - Escalonamento de Transações
Escalonamento completo: O escalonamento insere, para todas as transações, as ações de abort ou commit.
Escalonamento serial: O escalonamento não intercala as ações de transações diferentes.
Escalonamento equivalente: Para qualquer estado da base de dados, o efeito de executar um primeiro escalonamento é idêntico ao efeito de executar um segundo escalonamento.
Escalonamento serializável: Escalonamento equivalente a alguma execução serial das transações.
(Nota: Se cada transação preserva a consistência, todo escalonamento serializável preserva a consistência)
Defeitos atribuídos a Execuções Intercaladas
Duas ações no mesmo objeto conflitam se pelo menos uma delas é uma escrita (W).
Três defeitos podem ser descritos:
Leitura de dados que não foram salvos (Conflitos de WR, “leitura suja”):
T1: R(A), W(A), R(B), W(B), C
T2: R(A), W(A), R(B), W(B), C
Leitura não repetível (Conflitos RW):
T1: R(A), W(A), C
T2: R(A), W(A), C
Sobreposição de dados que não foram salvos
(Conflitos WW):
T1: W(A), W(B), C
T2: W(A), W(B), C
7 - Escalonamentos que Envolvem Transações Falhas
O escalonamento abaixo é irrecuperável:
T1: R(A), W(A-100), Abort
T2: R(A), W(A+6%), R(B), W(B+6%), C
Se T2 não tivesse sido completada, para recuperar a consistência, o aborto deveria ser feito em cascata.
Em um escalonamento recuperável, transações são completadas apenas depois que todas as transações que foram utilizadas por elas, completaram-se.
Outro problema potencial é referente ao tópico sobre desfazer as ações de transações:
T1: R(A), W(A+1), Abort
T2: R(A), W(A+1), C
Todas as alterações feitas por T1 são desfeitas restaurando os valores dos objetos participantes. as alterações de T2 também são perdidas, mesmo se T2 é completada.
Problemas desse gênero podem ser resolvidos através de técnicas de controle de concorrência.
8 - Controle de Concorrência Baseado em Bloqueio
Protocolo de bloqueio estrito de duas fases (Strict 2PL):
Cada transação deve obter:
• bloqueio compartilhado (S): sobre o objeto antes de sua leitura
• bloqueio exclusivo (X): sobre o objeto antes de sua escrita
Todos os bloqueios feitos por uma transação são liberados quando a transação é completada.
Se uma transação obtém um bloqueio do tipo exclusivo sobre um objeto, nenhuma outra transação pode obter um bloqueio (seja do tipo compartilhado ou exclusivo) sobre aquele objeto.
Variante => 2PL não-estrito:
Libera os bloqueios a qualquer hora, mas não pode obter mais nenhum bloqueio após a liberação de um bloqueio.
Controle de Concorrência Baseado em Bloqueio
Escalonamento sem controle de bloqueio:
T1: R(A), W(A), R(B), W(B), C
T2: R(A), W(A), R(B), W(B), C
Escalonamento com controle de bloqueio:
T1: X(A),R(A),W(A),X(B),R(B),W(B),C
T2: X(A)R(A), W(A), X(B),R(B),W(B),C
Se houvesse bloqueio S as transações poderiam serintercaladas.
O 2PL Estrito permite apenas escalonamentos serializáveis.
Adicionalmente, simplifica os abortos de transação
2PL não-estrito também permite apenas escalonamentos serializáveis, mas envolve um processamento mais complexo no aborto
9 - Abortando uma Transação
Se uma transação Ti é abortada, todas as suas ações devem ser desfeitas.
se Tj lê um objeto que foi escrito pela última vez por Ti, Tj também
deve abortar!
A maioria dos sistemas evita os abortos em cascata liberando os bloqueios da transação apenas no momento do commit.
Se Ti altera um objeto, Tj só pode ler este objeto após o commit de Ti.
Para desfazer (undo) as ações de uma transação abortada, o SGBD mantém um log no qual toda escrita é indicada.
Este mecanismo também é utilizado para recuperação após queda do sistema:
• todas as transações ativas no momento da queda são abortadas
quando o sistema é reiniciado.
O Log
As seguintes ações são gravadas no log:
Ti escreve um objeto: valor antigo e valor novo
O registro do log deve ser salvo no disco antes que a página seja modificada!
Ti commit/aborta: um registro do log indicando esta ação
Registros do log são associados a um identificador de transação, é fácil desfazer uma transação específica
O log é geralmente duplicado e armazenado em um meio de armazenamento estável
Todas as atividades registradas no log são tratadas de forma transparente pelo SGBD e de fato, todas as atividades relacionadas ao controle de concorrência como bloqueio/desbloqueio, tratamento de deadlocks
10 - Suporte a Transações em SQL
Uma transação é iniciada automaticamente, quando é executado um comando de acesso ao BD.
Uma transação executa um conjunto de comandos, e termina por um dos comandos COMMIT ou ROLLBACK.
SAVEPOINT (SQL-99) é um ponto da execução que define um estado que pode ser recuperado.
Associado ao conceito de transações aninhadas.
SAVEPOINT <savepoint name>
ROLLBACK TO SAVEPOINT <savepoint name>
11 - Recuperação de Falhas
O Gerenciador de Recuperação de Falhas garante a atomicidade e a durabilidade das transações.
Atomicidade: Desfazendo as ações das transações que não realizaram o commit.
Durabilidade: Todas as ações das transações que fizeram commit serão persistentes.
O Gerenciador é responsável por recuperar a consistência, após uma queda do sistema.
12 – Controle de Concorrência no SQLServer
O SQL Server implementa protocolos de controle de concorrência usando bloqueios. O protocolo utilizado pode ser configurado pelo usuário de acordo com suas necessidades. O usuário pode, por exemplo, indicar o grau de isolamento desejado entre transações, definindo como será feito o bloqueio dos dados, graus de isolamento também podem ser definidos para cada comando de uma transação.
Os graus de isolamento disponíveis são os seguintes:
Serializable: Só permite que escalas serializáveis sejam executadas bloqueando os dados até o final da transação, e impedindo a inserção de novas tuplas nas tabelas em uso. É o modo mais restritivo e que resulta em menor concorrência.
Repeatable read: Bloqueia os dados até o final da transação garantido que os valores dos dados acessados não serão modificados por outras transações, mas permite a inserção de novas tuplas na tabela, isso pode dar origem a "tuplas fantasma".
Read commited: Bloqueios são usados durante o acesso ao dado. Com isso, os valores dos dados acessados podem ser modificados por outras transações, e podem surgir "tuplas fantasma". Essa é a opção default.
Read incommited: Não usa bloqueio, podendo resultar em leitura de dados sendo escritos, valores dos dados acessados podem mudar durante a transação, e tuplas podem ser inseridas ou removidas durante a transação. É o modo menos restritivo, que resulta em maior concorrência, mas que deve ser usado somente quando não se tem nenhum compromisso com a consistência do resultado.
É possível indicar ao SQL Server como este deve efetuar os bloqueios referentes a um comando SQL passando “hints” ao SGBD.
O SQL Server permite também que o usuário configure o tempo máximo que uma transação pode ficar bloqueada esperando para acessar um dado (timeout). Qualquer transação que ficar bloqueada mais tempo que o timeout será abortada automaticamente, e o SQL Server indicará que ocorreu um erro de processamento.
Diferentes granularidades de bloqueio podem ser utilizadas para acessar o banco de dados. Para cada consulta processada, o SQL Server define automaticamente uma granularidade de bloqueio a ser usada. Em geral, quanto menores as porções bloqueadas no banco de dados, maior a concorrência, e maior a sobrecarga causada por bloqueios na execução de transações
O protocolo de bloqueio usado pelo SQL Server não impede que ocorram deadlocks. No entanto, o SQL Server detecta e recupera deadlocks automaticamente, escolhendo a transação que está em espera a menos tempo para ser abortada. O usuário pode modificar a forma como o SQL Server escolhe a transação a ser abortada atribuindo prioridades que são usadas para definir a transação que será abortada caso ocorra um deadlock.
Logs com checkpoints são usados para fazer a recuperação da base de dados. Para otimizar o acesso ao disco, as modificações nas bases de dados efetuadas pelas transações são adiadas, sendo efetuadas apenas quando ocorrer o próximo checkpoint.
Quando uma transação é efetivada, o SQL Server grava no log um registro de início da transação e as alterações nos valores dos dados efetuadas pela transação, seguidas de uma indicação de final da transação.
No instante em que ocorre um checkpoint, as alterações nos valores dos dados feitas por transações efetivadas desde o checkpoint anterior são gravadas no disco, e o checkpoint é marcado no log. Checkpoints ocorrem periodicamente e quando os comandos alter database, checkpoint e shutdown são executados.
Em caso de falha, a base de dados é recuperada, refazendo as transações efetivadas logo após o último checkpoint e ignorando as alterações registradas no log referentes a transações não efetivadas. Este procedimento mantém a consistência das bases de dados.
Vale observar que o ambiente cliente-servidor vai migrando paulatinamente ao ambiente de aplicações distribuídas.Nela uma transação pode requisitar dados ou serviços que estão distribuídos em mais de um servidor com múltiplos servidores envolvidos em uma transação tanto pela requisição direta do cliente quanto indiretamente via servidor.
Em uma aplicação distribuída, quando o cliente invoca todos os servidores necessários para completar a transação requisitada é chamada transação distribuída simples, enquanto quando o cliente requisita uma transação ao servidor que por sua vez invoca outros servidores e assim sucessivamente tem-se uma transação aninhada.
Transações aninhadas podem ser executadas concorrentemente em diferentes servidores e podem ser confirmadas ou abortadas independentemente.
O atual ambiente de desenvolvimento envolve conceitos complexos exigindo grande dedicação dos profissionais para se manterem atualizados.
12 – Conclusão
Controle de concorrência e recuperação estão entre as funções mais importantes oferecidas por um SGBD.
Os usuários não precisam se preocupar com a concorrência, pois sistema automaticamente insere pedidos de bloqueio/desbloqueio e escalona as ações de diferentes transações de forma a garantir que a execução resultante seja equivalente à execução serial das transações.
O Write-ahead logging (WAL) é usado para desfazer ações de transações abortadas e para restaurar o sistema a um estado consistente após uma falha.
13 – Referências
Materiais em meio eletrônico:
UNICAMP/IC/MO410/MC536/2003-5 - Slides do livro Database Management Systems 3ed, R. Ramakrishnan and J. Gehrke, McGrow-Hill, 2003.
– Disponível em: <http://www.ic.unicamp.br/~geovane/mo410-071/Ch16-GerTrans_pt.pdf> Acesso em: 03 outubro de 2008.