Bases de Dados Concorrência Transacções concorrentes exemplo T 1 : B := B 50 write(b) A := A + 50 write(a) T 2 : display(a+b) T 2 pode dar um resultado inconsistente quando executada em paralelo com T 1 2 1
Locks Existem 2 modos de bloquear o acesso a um objecto modo partilhado (S) o objecto pode ser lido, mas não escrito várias transacções podem possuir este lock num dado momento modo exclusivo (X) o objecto pode ser lido e escrito apenas uma transacção pode possuir este lock num dado momento 3 Compatibilidade de locks Uma transacção que pede o lock de um objecto só continua quando o lock é finalmente concedido só o recebe o lock quando não houver ou forem libertados todos os locks incompatíveis Tabela de compatibilidade de locks S = partilhado (shared) X = exclusivo 4 2
Locks e transacções exemplo T 1 com locks T 1 : lock-x(b) B := B 50 write(b) unlock(b) lock-x(a) A := A + 50 write(a) unlock(a) 5 Locks e transacções exemplo T 2 com locks T 2 : lock-s(a) unlock(a) lock-s(b) unlock(b) display(a+b) 6 3
Locks e transacções exemplo T 1 : lock-x(b) B := B 50 write(b) unlock(b) lock-x(a) A := A + 50 write(a) unlock(a) T 2 : lock-s(a) unlock(a) lock-s(b) unlock(b) display(a+b) possibilidade de execução de T 1 possibilidade de execução de T 2 7 Protocolo de 2 fases Para garantir serialização, cada transacção deve ter 2 fases fase de aquisição de locks a transacção pode adquirir vários locks e não pode libertar nenhum fase de libertação de locks a transacção pode libertar os locks e não pode adquirir nenhum 8 4
Locks e transacções exemplo T 1 : lock-x(b) B := B 50 write(b) lock-x(a) A := A + 50 unlock(b) write(a) unlock(a) T 2 : lock-s(a) lock-s(b) unlock(b) unlock(a) display(a+b) 9 Situação de deadlock exemplo T 3 bloqueia porque T 4 tem um lock incompatível T 4 bloqueia porque T 3 tem um lock incompatível T 3 ou T 4 terá que sofrer rollback para resolver este impasse (deadlock) 10 5
Situação de starvation Situação de starvation se o sistema detectar um deadlock, faz rollback de uma das transacções e lança outra vez se a mesma transacção voltar a causar deadlock, sofre rollback novamente etc. (a transacção pode nunca ser executada até ao fim) 11 Bases de Dados Recuperação 6
Necessidade de recuperação exemplo No passo 5 sistema já executou write(a) sistema sofre um crash antes de write(b) 1 2 3 4 5 6 T 1 : A := A 50 write(a) B := B + 50 write(b) Estas estratégias de recuperação não funcionam: não fazer nada falta somar 50 a B fazer tudo outra vez subtrai outros 50 a A 13 Modificações registadas em log Todas as modificações à BD são registadas num log cada registo do log contém identificação da transacção identificação do objecto modificado valor antigo do objecto (V 1 ) novo valor do objecto (V 2 ) exemplos <T i start > início da transacção T i <T i, Q, V 1, V 2 > T i escreve no objecto Q o valor V 2 <T i commit > transacção T i completou <T i abort > ou a transacção T i falhou 14 7
Exemplo Seja A=1000, B=2000, C=700 Se T 1 e T 2 forem executadas em série <T 1, A, 1000, 950 > <T 1, B, 2000, 2050 > <T 1 commit > <T 2, C, 700, 600 > <T 2 commit > T 1 : A := A 50 write(a) B := B + 50 write(b) T 2 : read(c) C := C 100 write(c) 15 Modificações no log e modificações na BD Aspectos importantes os eventos são escritos no log antes das respectivas modificações serem feitas na BD regra conhecida por WAL (write-ahead logging) estar no log não quer dizer que já tenha sido feito uma transacção T i é considerada completa quando o registo <T i commit > é escrito no log a partir daí, mesmo que haja um crash, é possível recuperar repetindo a transacção 16 8
Exemplo Caso 1 <T 1, A, 1000, 950 > <T 1, B, 2000, 2050 > --- crash!! --- e quando o sistema reinicia Caso 2 <T 1, A, 1000, 950 > <T 1, B, 2000, 2050 > <T 1 commit > <T 2, C, 700, 600 > --- crash!! --- Caso 3 <T 1, A, 1000, 950 > <T 1, B, 2000, 2050 > <T 1 commit > <T 2, C, 700, 600 > <T 2 commit > --- crash!! --- T 1 sofre undo T 2 sofre undo; T 1 sofre redo T 1 e T 2 sofrem redo 17 Recuperação O sistema recupera a partir do log da seguinte forma undo(t i ) a transacção T i é invertida se o log contém <T i start > mas não <T i commit > o valor antigo em < T i, Q, V antigo, V novo > é reposto redo(t i ) a transacção T i é repetida se o log contém <T i start > e <T i commit > 18 9
Utilização de checkpoints Para evitar refazer tudo o que está no log fazem-se checkpoints periódicos de tempos a tempos, transfere-se os dados em memória para o disco em seguida(*) regista-se <checkpoint> no log A recuperação pode envolver transacções que começaram antes do checkpoint pesquisar o log para trás até encontrar o primeiro checkpoint o checkpoint indica que transacções estavam activas nesse momento: <checkpoint T 1 T 2 > (*) repare-se que isto é uma excepção ao princípio de write-ahead logging 19 Utilização de checkpoints exemplo checkpoint crash!! t T 1 T 2 T3 T 4 T 1 pode ser ignorada (resultados foram já escritos no checkpoint) T 2 e T 3 têm de ser repetidas T 4 tem de ser invertida 20 10
Recuperação com transacções concorrentes Análise do log após crash do sistema o log é percorrido para trás até encontrar o último checkpoint (a) para cada registo na forma <T i commit > T i é adicionada à lista de transacções a repetir (redo-list) (b) para cada registo na forma <T i start > se T i não estiver na redo-list então é adicionada à lista de transacções a inverter (undo-list) às transacções em < checkpoint T 1 T 2 > aplica-se o caso (b) 21 Recuperação com transacções concorrentes Uma vez construídas as listas redo-list e undo-list (1) o sistema volta a percorrer o log para trás para cada <T i, Q j, V 1, V 2 > verifica se T i está na undo-list e, em caso afirmativo, inverte essa operação quando o <T i start > de todas as transacções na undo-list tiverem sido encontrados, o sistema passa à fase (2) (2) localiza o < checkpoint T 1 T 2 > mais recente pode estar atrás ou à frente da posição actual (3) percorre o log para a frente a partir do checkpoint para cada <T i, Q, V 1, V 2 > encontrado, verifica se T i está na redo-list e, em caso afirmativo, repete essa operação 22 11
Exemplo <T 0 start > <T 0, A, 0, 10 > <T 0 commit > <T 1, B, 0, 10 > <T 2, C, 0, 10 > <T 2, C, 10, 20 > < checkpoint T 1,T 2 > <T 3 start > <T 3, A, 10, 20 > <T 4 start > <T 3, D, 0, 10 > <T 4, E, 0, 10 > <T 3 commit > --- crash!! --- 23 Exemplo construção das listas <T 0 start > <T 0, A, 0, 10 > <T 0 commit > <T 1, B, 0, 10 > <T 2, C, 0, 10 > <T 2, C, 10, 20 > < checkpoint T 1,T 2 > <T 3 start > <T 3, A, 10, 20 > <T 4 start > <T 3, D, 0, 10 > <T 4, E, 0, 10 > <T 3 commit > undo-list = { T 4, T 1, T 2 } redo-list = { T 3 } 24 12
Exemplo fase 1 <T 0 start > <T 0, A, 0, 10 > <T 0 commit > <T 1, B, 0, 10 > <T 2, C, 0, 10 > <T 2, C, 10, 20 > < checkpoint T 1,T 2 > <T 3 start > <T 3, A, 10, 20 > <T 4 start > <T 3, D, 0, 10 > <T 4, E, 0, 10 > <T 3 commit > undo-list = { T 4, T 1, T 2 } repõe valor 0 em B repõe valor 0 em C repõe valor 10 em C repõe valor 0 em E 25 Exemplo fases 2 e 3 <T 0 start > <T 0, A, 0, 10 > <T 0 commit > <T 1, B, 0, 10 > <T 2, C, 0, 10 > <T 2, C, 10, 20 > < checkpoint T 1,T 2 > <T 3 start > <T 3, A, 10, 20 > <T 4 start > <T 3, D, 0, 10 > <T 4, E, 0, 10 > <T 3 commit > redo-list = { T 3 } repete escrita de valor 20 em A repete escrita de valor 10 em D 26 13