Sistemas Operacionais

Aula 8: Transações Atômicas

Transações atômicas

Uma coleção de operações que executa uma função lógica forma uma transação.

Para se garantir que a consistência dos dados é necessário garantir-se que transações sejam executadas de maneira correta: atômica:

Uma maneira de se garantir que a transação é executada de maneira correta pode-se o fazer em exclusão mútua.

Mas isto não é uma boa idéia...

Transações Mutex

Porque muitas vezes trava-se muito mais do que necessário:

Transações Atômicas

Vários problemas podem afetar o resultados das transações:

Classificação do Armazenamento

Vamos estudar protocolos de sobrevivência a falhas de armazenamento volátil somente.

Exemplo de Transação

vende_peça(peça, quant, valor, cliente)
{
  read(estoque, peça);
  estoque->quant -= quant;
  write(estoque, peça);
  read(controle, ultima_transação);
  ultima_transação++;
  write(controle, ultima_transação);
  write(transações, ultima_transação,
        VENDA, peça, quant, valor, data);
  write(contas_a_receber, data, valor,
        cliente);
}

Recuperação usando Log

Usa-se um arquivo ``diário'' em armazenamento estável para gravar as partes da transação que já foram executadas: arquivo log.

Grava-se neste arquivo toda e qualquer operação antes de se a executar.

Exemplo de Log Recovery

vende_peça(peça, quant, valor, cliente)
{
  write(log, ``T%d starts'', i);
  read(estoque, peça);
  estoque->quant -= quant;
  write(log, estoque, peçaold, peça);
  write(estoque, peça);
  read(controle, ult_tr_#);
  ultima_transação++;
  write(log, controle,
        ult_tr_#old, ul_tr_#);
  write(controle, ultima_transação);
  write(log, transações, ...);
  write(transações, ultima_transação,
        VENDA, peça, quant, valor, data);
  write(log, contas_a_receber, ...);
  write(contas_a_receber, data, valor,
        cliente);
  write(log, ``T%d commits'', i);
}

Recuperação usando Log

Fácil de implementar as funções undo(i) e redo(i).

Cuidados:

Checkpoints

A fim de diminuir o tempo de recuperação o sistema grava checkpoints da seguinte maneira:

Recuperação só é feita a partir do último checkpoint gravado no log.

Transações Atômicas Concorrentes

Se mais de uma transação pode estar ocorrendo ao mesmo tempo é necessário garantir-se a serializabi-lidade (!). O efeito tem que ser:

vende_peça(peça, quant, valor, cliente)
{
  read(estoque, peça);
  estoque->quant -= quant;
  write(estoque, peça);
  read(controle, ultima_transação);
  ultima_transação++;
  write(controle, ultima_transação);
  write(transações, ultima_transação,
        VENDA, peça, quant, valor, data);
  write(contas_a_receber, data, valor,
        cliente);
}

Locking Protocol

Para se garantir a seriali....., este negócio ai, podemos usar o protocolo:

Cada acesso trava o registro no arquivo:

good_read(arquivo, id) {
  lock(mutex);
  while (r == ``locked'')
    read(arquivo, id, r);
  write(arquivo, id, ``locked'');
  unlock(mutex);
  return(r);
};

Two Phase Locking Protocol

O protocolo de leitura e escrita consiste de 2 fases:

Resumindo, na hora em que o primeiro write for executado, nenhum read pode ser mais.

Este protocolo:

Two Phase vende_peça

vende_peça(peça, quant, valor, cliente)
{
  /* growing phase */
  read(estoque, peça);
  estoque->quant -= quant;
  read(controle, ultima_transação);
  read(transações);
  read(contas_a_receber);

  /* shrinking phase */
  write(estoque, peça);
  ultima_transação++;
  write(controle, ultima_transação);
  write(transações, ultima_transação,
        VENDA, peça, quant, valor, data);
  write(contas_a_receber, data, valor,
        cliente);
}