12.07.2015 Views

Introdução às Bases de Dados Paralelas e Distribuídas

Introdução às Bases de Dados Paralelas e Distribuídas

Introdução às Bases de Dados Paralelas e Distribuídas

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Arquitecturas <strong>de</strong> Sistemas <strong>de</strong> Base <strong>de</strong> <strong>Dados</strong>• Sistemas Centralizados• Sistemas Cliente-Servidor• Sistemas Paralelos• Sistemas Distribuídos<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IISistemas Centralizados• Correm sobre um único computador e não interagem com outrossistemas.• Sistema genérico <strong>de</strong> computador: um ou mais CPUs e umnúmero <strong>de</strong> controladores que estão ligados por um bus comumque permite o acesso a memória partilhada.• Sistema Single-user (e.g., computador pessoal ou workstation):unida<strong>de</strong> <strong>de</strong>sk-top, single user, normalmente tem um único CPUe um ou dois discos rígidos; o SO po<strong>de</strong>rá suportar apenas umutilizador.• Sistema Multi-user: mais discos, mais memória, vários CPUs, eSO multi-user. Serve um número gran<strong>de</strong> <strong>de</strong> utilizadores queestão ligados ou sistema através <strong>de</strong> terminais. São muitas vezeschamados <strong>de</strong> sistemas servidor.<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II1


Um Sistema Centralizado<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IISistemas Cliente-Servidor• Sistemas Servidor respon<strong>de</strong>m a pedidos gerados em m sistemasclientes, cuja estrutura genérica é mostrada abaixo:<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II2


Sistemas Cliente-Servidor(Cont.)• As funcionalida<strong>de</strong>s das BD’s po<strong>de</strong>m ser divididas em:ê Back-end: gerem estruturas <strong>de</strong> acesso, avaliação <strong>de</strong> consultas eoptimização, controlo <strong>de</strong> concorrência e recuperação.ê Front-end: consiste em ferramentas tais como formulários, geradores<strong>de</strong> relatório, e interfaces gráficas do utilizador.• A interface entre o front-end e o back-end é através <strong>de</strong> SQL ouatravés <strong>de</strong> uma API (application program interface).<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IISistemas Cliente-Servidor(Cont.)• Vantagens da substituição <strong>de</strong> mainframes por re<strong>de</strong>s <strong>de</strong>workstations ou computadores pessoais ligados a máquinasservidoras <strong>de</strong> back-end:ê Melhor relação funcionalida<strong>de</strong>/custoê Flexibilida<strong>de</strong> na atribuição <strong>de</strong> recursos e capacida<strong>de</strong>s <strong>de</strong> expansãoê Melhores interfaces <strong>de</strong> utilizadorê Manutenção mais fácil• Os sistemas servidores po<strong>de</strong>m ser classificados em dois tipos:ê Servidores transaccionais que são largamente usados emsistemas <strong>de</strong> base <strong>de</strong> dados relacionais, eê Servidores <strong>de</strong> dados, usados em sistemas <strong>de</strong> base <strong>de</strong> dadosorientados por objectos.<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II3


Servidores Transaccionais• Também chamados sistemas servidores <strong>de</strong> consultas ou SQLserver systems; os clientes enviam pedidos para o sistemaservidor on<strong>de</strong> as transacções são executadas, e os resultadossão enviados <strong>de</strong> volta para o cliente.• Os pedidos são especificados em SQL, e comunicados aoservidor através <strong>de</strong> um mecanismo <strong>de</strong> remote procedure call(RPC).• RPC transaccional permite que várias chamadas RPC formemcolectivamente uma transacção.• Open Database Connectivity (ODBC) é uma API em linguagemC da Microsoft que <strong>de</strong>fine um standard para ligação a umservidor, enviando pedidos SQL, e recebendo os resultados.• JDBC é um standard similar a ODBC, para Java<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IIEstrutura <strong>de</strong> processos <strong>de</strong> um sistematransaccional• Um servidor transaccional típico possui múltiplos processos aace<strong>de</strong>r a dados em memória partilhada.• Processos Servidorê Recebem consultas dos utilizadores (transacções), executam-nas eenviam o resultado <strong>de</strong> voltaê Os processos po<strong>de</strong>m ser multithrea<strong>de</strong>d, permitindo que um únicoprocesso possa executar várias consultas concorrentementeê Temos tipicamente múltiplos processos servidor multithrea<strong>de</strong>d• Processo <strong>de</strong> gestão <strong>de</strong> Locksê Veremos mais àfrente• Processo <strong>de</strong> escrita na Base <strong>de</strong> <strong>Dados</strong>ê O buffer <strong>de</strong> output modificado é escrito em blocos no discocontinuamente<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II4


Processos do Servidor Transaccional (Cont.)• Processo <strong>de</strong> escrita <strong>de</strong> Logê Os processos servidor adicionam registos log ao buffer <strong>de</strong> registos logê O processo <strong>de</strong> escrita <strong>de</strong> Log guarda os registos <strong>de</strong> log em suportenão-volátil.• Processo checkpointê Executa checkpoints periódicos• Processo monitor <strong>de</strong> processosê Monitoriza os outros processos, e toma medidas <strong>de</strong> recuperação sealgum <strong>de</strong>stes processos falha‣ E.g. abortar as transacções a serem executadas por um processoservidor e reiniciar o processo<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IIProcessos do Servidor Transaccional (Cont.)<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II5


Processos do Servidor Transaccional (Cont.)• A memória partilhada contém dados partilhadosê Buffer poolê Lock tableê Log bufferê Consultas em cache (reusadas se a mesma consulta volta a sersubmetida)• Todos os processos da BD po<strong>de</strong>m ace<strong>de</strong>r àmemória partilhada• Para assegurar que dois processos não estão a ace<strong>de</strong>r àmesma estrutura <strong>de</strong> dados ao mesmo tempo, os SGBDimplementam exclusão mútua usando alternativamente:ê Semáforos do sistema operativoê Instruções atómicas tais como test-and-set<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IIProcessos do Servidor Transaccional (Cont.)• Para evitar o overhead da comunicação interprocessos parapedido/atribuição <strong>de</strong> lock, cada processo da base <strong>de</strong> dados operadirectamente sobre a estrutura <strong>de</strong> dados da tabela <strong>de</strong> lock em vez <strong>de</strong> enviarpedidos para o processo <strong>de</strong> gestão <strong>de</strong> locksê Exclusão mútua na tabela <strong>de</strong> locks é assegurada usando semáforos, ou maisusualmente, instruções atómicasê Se um lock po<strong>de</strong> ser obtido, a tabela <strong>de</strong> lock é actualizada directamente namemória partilhadaê Se um lock não po<strong>de</strong> ser obtido imediatamente, o pedido <strong>de</strong> lock é anotado natabela <strong>de</strong> lock e o processo (ou thread) espera até o lock ser concedidoê Quando um lock é libertado, o processo que o liberta actualiza a tabela <strong>de</strong> lockpara registar a libertação do lock, e conce<strong>de</strong> o lock aos pedidos em espera (sehouver algum)ê O processo/thread à espera <strong>de</strong> lock po<strong>de</strong> alternativamente:‣ Ler continuamente a tabela <strong>de</strong> lock para verificar a concessão <strong>de</strong> lock, ou‣ Usar o mecanismo <strong>de</strong> semáforos do sistema operativo para esperar numsemáforo.– O i<strong>de</strong>ntificador <strong>de</strong> semáforo é guardado na tabela <strong>de</strong> lock– Quando o lock é libertado, o processo que o libertou sinaliza o semáforopara dizer ao processo/thread para prosseguir• O processo <strong>de</strong> gestão <strong>de</strong> locks é usado para <strong>de</strong>tecção <strong>de</strong> <strong>de</strong>adlocks<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II6


Servidores <strong>de</strong> <strong>Dados</strong><strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II• Usados em LANs, on<strong>de</strong> existe uma conexão <strong>de</strong> velocida<strong>de</strong>muito alta entre os clientes e o servidor, as máquinas cliente temum po<strong>de</strong>r <strong>de</strong> processamento comparável ao servidor, e astarefas a executar são computacionalmente complexas.• Enviar dados para as máquinas cliente on<strong>de</strong> o processamenetoé efectuado, e <strong>de</strong>pois os resultados são enviados <strong>de</strong> volta parao servidor.• Esta arquitectura requer uma completa funcionalida<strong>de</strong> <strong>de</strong> backendnos clientes.• É usado em muito OO-SGBD• Algumas questões:ê Page-Shipping versus Item-Shippingê Lockingê Data Cachingê Lock CachingServidores <strong>de</strong> <strong>Dados</strong> (Cont.)• Page-Shipping versus Item-Shippingê Unida<strong>de</strong> <strong>de</strong> envio mais pequena ⇒ mais mensagensê Compensa o prefetch <strong>de</strong> items relacionados junto com o item pedidoê Page shipping po<strong>de</strong> ser visto como uma forma <strong>de</strong> prefetching• Lockingê O overhead <strong>de</strong> pedir e obter locks do servidor é alto <strong>de</strong>vido aos tempos dasmensagensê Po<strong>de</strong>mos atribuir locks nos items requeridos e prefetched; com pageshipping, uma transacção obtem lock sobre toda a página.ê Locks num item prefetched po<strong>de</strong>m ser called back pelo servidor, e éretornado pela transacção cliente se o item prefetched não foi usado.ê Locks sobre a página po<strong>de</strong>m ser <strong>de</strong>sescalados para locks sobre items napágina quando existem conflitos <strong>de</strong> locks. Locks sobre items não usadospo<strong>de</strong>m então ser retornados ao servidor.<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II7


Servidores <strong>de</strong> <strong>Dados</strong> (Cont.)• Data Cachingê Os dados po<strong>de</strong>m ser mantidos em cache no cliente mesmo entre transacçõesê No entanto, é fundamental verificar a actualida<strong>de</strong> dos dados antes da suautilização (cache coherency)ê A verificação po<strong>de</strong> ser feita aquando do pedido <strong>de</strong> lock do item• Lock Cachingê Os locks po<strong>de</strong>m ser mantidos pelo sistema cliente mesmo entre transacçõesê As transacções po<strong>de</strong>m obter os locks em cache localmente, sem contactar oservidorê O servidor po<strong>de</strong> fazer o call back <strong>de</strong> locks dos clientes quando recebe pedidosconflituosos <strong>de</strong> locks. O cliente <strong>de</strong>volve o lock assim que não hajamtransacções locais a usá-lo.ê Similar a <strong>de</strong>escalation, mas entre transacções.<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IISistemas Paralelos• Sistemas <strong>de</strong> base <strong>de</strong> dados paralelos consistem em múltiplosprocessadores e múltiplos discos ligados por uma re<strong>de</strong> <strong>de</strong>interconexão rápida.• Uma máquina paralela coarse-grain consiste num númeropequeno <strong>de</strong> procedores po<strong>de</strong>rosos• Uma máquina massivamente paralela ou fine grain utilizamilhares <strong>de</strong> processadores mais pequenos.• Existem duas medidas <strong>de</strong> performance principais:ê throughput --- o número <strong>de</strong> tarefas que po<strong>de</strong>m ser completadasdados um intervalo <strong>de</strong> tempoê Tempo <strong>de</strong> resposta --- o tempo necessário para que uma tarefasubmetida seja completada<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II8


Speed-Up e Scale-Up• Speedup: um problema <strong>de</strong> tamanho fixo executado num sistemapequeno é dado a um sistema N-vezes maior.ê Medido por:speedup = tempo no sistema pequenotempo no sistema gran<strong>de</strong>ê Speedup é linear se o quociente é igual a N.• Scaleup: aumentar o tamanho do problema e do sistemaê Um sistema N-vezes maior é usado para resolver uma tarefa N-vezes maiorê Medido por:scaleup = tempo do problema pequeno no sistema pequenotempo do problema gran<strong>de</strong> no sistema gran<strong>de</strong>ê Scale up é linear se o quociente é igual a 1.<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IISpeedupSpeedup<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II9


ScaleupScaleup<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IIScale <strong>de</strong> batch e <strong>de</strong> transações• Scaleup <strong>de</strong> Batch:ê Uma única gran<strong>de</strong> tarefa; típico em muitas consultas a bases <strong>de</strong>dados e em simulação científica.ê Usar um computador N-vezes maior num problema N-vezes maior.• Scaleup <strong>de</strong> transacções:ê Um gran<strong>de</strong> número <strong>de</strong> pequenas consultas submetidas porutilizadores in<strong>de</strong>pen<strong>de</strong>ntes a uma base <strong>de</strong> dados partilhada; típicoem processamento <strong>de</strong> transacções e sistemas <strong>de</strong> tempo partilhado.ê N-vezes mais utilizadores a submeter pedidos a uma base <strong>de</strong>dados N-vezes maior, sobre um computador N-vezes maior.ê Apropriada para execução paralela.<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II10


Factores limitativos <strong>de</strong> Speedup e ScaleupSpeedup e scaleup são muitas vezes sublineares <strong>de</strong>vido a:• Custo <strong>de</strong> inicialização: O custo <strong>de</strong> inicializar múltiplosprocessos po<strong>de</strong> dominar o tempo <strong>de</strong> computação, se o grau <strong>de</strong>paralelismo for elevado.• Interferência: Os processos a ace<strong>de</strong>r a recursos partilhados(e.g.,bus do sistema, discos, ou locks) competem entre si,gastando tempo à espera <strong>de</strong> outros processos, em vez <strong>de</strong>executarem trabalho útil.• Skew: Aumentando o grau <strong>de</strong> paralelismo aumenta-se avariação nos tempos <strong>de</strong> execução das tarefas paralelas. Otempo global <strong>de</strong> execução é <strong>de</strong>terminado pela mais <strong>de</strong>moradadas tarefas paralelas.<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IIArquitecturas <strong>de</strong> Re<strong>de</strong>s <strong>de</strong> Interconexão• Bus. As componentes do sistema enviam e recebem dados porum único bus <strong>de</strong> comunicação;ê Dificulda<strong>de</strong>s <strong>de</strong> escalabilida<strong>de</strong> com o aumento <strong>de</strong> paralelismo.• Mesh. As componentes são configuradas como nós numagrelha, e cada componente é ligada a todas as componentesadjacentesê As ligações aumentam com o número crescente <strong>de</strong> componentes, epor isso tem melhor escalabilida<strong>de</strong>.ê Mas po<strong>de</strong> requerer percorrer 2√nligações para enviar umamensagem para um nó.• Hipercubo. As componentes são numeradas em binário; ascomponentes são ligadas umas <strong>às</strong> outras se as suasrepresentações binárias diferem em exactamente um bit.ê n componentes estão ligadas a outras log(n) componentes e po<strong>de</strong>mchegar a qualquer outra percorrem no máximo log(n) ligações;reduz os tempos <strong>de</strong> comunicação.<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II11


Arquitecturas <strong>de</strong> Interconexão<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IIArquitecturas <strong>de</strong> <strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> <strong>Paralelas</strong>• Memória partilhada –os processadores partilham a mesmamemória• Disco partilhado –os processadores partilham o mesmo disco• Shared nothing –os processadores não partilham memórianem disco• Hierárquico –híbrido das arquitecturas acima<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II12


Arquitecturas <strong>de</strong> <strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> <strong>Paralelas</strong><strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IIMemória Partilhada• Os processadores e os discos tem acesso a uma memóriacomum, tipicamente através <strong>de</strong> um bus ou <strong>de</strong> uma re<strong>de</strong> <strong>de</strong>interconexão.• Comunicação entre processadores extremamente eficiente –osdados na memória partilhada po<strong>de</strong>m ser acedidos por qualquerprocessador sem terem que ser movidos por software.• Desvantagem –a arquitectura não é escalável para além <strong>de</strong> 32ou 64 processadores uma vez que o bus ou a re<strong>de</strong> <strong>de</strong>interconexão se tornam num bottleneck• Bastante usada para níveis baixos <strong>de</strong> paralelismo (4 a 8).<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II13


Disco Partilhado• Todos os processadores po<strong>de</strong>m ace<strong>de</strong>r directamente a todos osdiscos através <strong>de</strong> uma re<strong>de</strong> <strong>de</strong> interconexão, mas osprocessadores tem memórias privadas.ê O bus <strong>de</strong> memória <strong>de</strong>ixa <strong>de</strong> ser um bottleneckê A arquitectura fornece um grau <strong>de</strong> tolerancia a falhas —se umprocessador falha, os outros processadores po<strong>de</strong>m assumir as suatarefas uma vez que a base <strong>de</strong> dados resi<strong>de</strong> em discos que sãoacessiveis <strong>de</strong> todos os processadores.• Exemplos: IBM Sysplex e DEC clusters (agora Compaq) acorrer Rdb (agora Oracle Rdb) foram utilizadores comerciaispioneiros• Desvantagem: o bottleneck ocorre na re<strong>de</strong> <strong>de</strong> interconexão dosdiscos.• Sistemas <strong>de</strong> disco-partilhado são escaláveis num número maior<strong>de</strong> processadores, mas a comunicação entre processadores émais lenta.<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IIShared Nothing• Cada nó consiste num processador, memória e um ou maisdiscos. Os processadores num nó comunicam com outroprocessador usando a re<strong>de</strong> <strong>de</strong> interconexão. Cada nó funcionacomo um servidor para os dados resi<strong>de</strong>ntes nos seus própriosdiscos.• Exemplos: Teradata, Tan<strong>de</strong>m, Oracle-n CUBE• Os dados acedidos dos discos locais (e da memória local) nãopassam pela re<strong>de</strong> <strong>de</strong> interconexão, logo minimizando ainterferencia da partilha <strong>de</strong> recursos.• Multi-processadores Shared-nothing po<strong>de</strong>m ser escalados emmilhares <strong>de</strong> processadores sem interferência.• Desvantagem principal: custo <strong>de</strong> comunicação e acesso adiscos não-locais; envio <strong>de</strong> dados envolve interacção <strong>de</strong>software nos dois extremos.<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II14


Hierárquico• Combina as características das arquitecturas <strong>de</strong> memóriapartilhada, disco partilhado e shared-nothing.• O nível mais alto é uma arquitectura shared-nothing – os nósestão ligados por uma re<strong>de</strong> <strong>de</strong> interconexão, e não partilhamentre si disco e memória.• Cada nó do sistema po<strong>de</strong> ser um sistema <strong>de</strong> memória partilhadacom alguns processadores.• Alternativamente, cado nó po<strong>de</strong> ser um sistema <strong>de</strong> discopartilhado, e cada um dos sistemas partilhando um conjunto <strong>de</strong>discos po<strong>de</strong> ser um sistema <strong>de</strong> memória partilhada.• A complexida<strong>de</strong> <strong>de</strong> programação <strong>de</strong> tais sistema é reduzidausando arquitecturas <strong>de</strong> memória virtual distribuídaê Também chamadas non-uniform memory architecture (NUMA)<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IISistemas Distribuídos• Os dados estão espalhados por várias máquinas (tambémreferidos por sites ou nós.)• A re<strong>de</strong> interliga as máquinas• Os dados são partilhados pelos utilizadores nas várias máquinas<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II15


<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> <strong>Distribuídas</strong>• <strong>Bases</strong> <strong>de</strong> dados distribuídas homogéneasê O mesmo software/esquema é usados em todos os sites, os dadospo<strong>de</strong>m estar repartidos entre os sitesê Objectivo: fornecer uma visão <strong>de</strong> uma única base <strong>de</strong> dados,escon<strong>de</strong>ndo <strong>de</strong>talhes <strong>de</strong> distribuição• <strong>Bases</strong> <strong>de</strong> dados distribuídas heterogéneasê Software/esquema diferentes em diferentes sitesê Objectivo: integrar bases <strong>de</strong> dados existentes para fornecerfuncionalida<strong>de</strong>s úteis• Diferenciação entre transacção local e globalê Uma transacção local ace<strong>de</strong> a dados num único site on<strong>de</strong> atransacção foi iniciada.ê Uma transacção global ace<strong>de</strong> a dados que ou estão num sitediferente daquele em que a transacção foi iniciada ou ace<strong>de</strong> adados em vários sites diferentes.<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> IITra<strong>de</strong>-offsem Sistemas Distribuídos• Partilha <strong>de</strong> dados – os utilizadores num site po<strong>de</strong>m ace<strong>de</strong>r adados resi<strong>de</strong>ntes em outros sites.• Autonomia –cada site po<strong>de</strong> manter um nível <strong>de</strong> controlo sobreos dados guardados localmente.• Maior disponibilida<strong>de</strong> do sistema através <strong>de</strong> redundância —osdados po<strong>de</strong>m estar replicados em sites remotos, e o sistemapo<strong>de</strong> funcionar mesmo que um site falhe.• Desvantagem: a complexida<strong>de</strong> aumenta pois é necessárioassegurar uma coor<strong>de</strong>nação correcta entre os sites.ê Custo <strong>de</strong> <strong>de</strong>senvolvimento <strong>de</strong> software.ê Maior possiblida<strong>de</strong> <strong>de</strong> bugs.ê Aumento do overhead <strong>de</strong> processamento.<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II16


Aspectos <strong>de</strong> Implementação para <strong>Bases</strong> <strong>de</strong><strong>Dados</strong> <strong>Distribuídas</strong>• Atomicida<strong>de</strong> é necessária mesmo para transacções que actualizam dadosem mais do que um siteê Uma transacção não po<strong>de</strong> ser committed num site e abortada noutro• Para assegurar atomicida<strong>de</strong> é usado o two-phase commit protocol (2PC)ê I<strong>de</strong>a básica: cada site executa a transacção até mesmo antes do commit, e<strong>de</strong>ixa a <strong>de</strong>cisão final para um coor<strong>de</strong>nadorê Cada site tem que seguir a <strong>de</strong>cisão do coor<strong>de</strong>nador: mesmo que haja umafalha enquanto se espera pela <strong>de</strong>cisão do coor<strong>de</strong>nador‣ Para isso os updates das transacções são registados em suportes estavéise a transacção é marcada como “waiting”• 2PC nem sempre é apropriado: outros mo<strong>de</strong>los <strong>de</strong> transacções baseadosem mensagens persistentes também são usados• É necessário o controlo <strong>de</strong> concorrência distribuída (e <strong>de</strong> <strong>de</strong>tecção <strong>de</strong><strong>de</strong>adlocks)• É necessária a replicação <strong>de</strong> dados para melhorar a disponibilida<strong>de</strong> <strong>de</strong>dados<strong>Bases</strong> <strong>de</strong> <strong>Dados</strong> II17

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!