Construindo um Blockchain: The Gray Paper

Background

O trem de excitação do blockchain está em um alto histórico! Existem inúmeros artigos e notícias que o chamam de maior invenção desde a internet. Por outro lado, há um acampamento igualmente grande dizendo que, embora a tecnologia seja ótima, não existe um caso de uso real .

Até recentemente, estive em algum lugar do meio. Intrigado por blockchain comecei a pesquisá-lo. Depois de ler vários artigos e white papers, senti-me confortável com alguns dos termos e conceitos. No entanto, eu ainda não tinha esse momento “aha” O conteúdo que eu estava lendo era um nível muito alto e não transmitia claramente o poder eo potencial de construção de aplicativos distribuídos e descentralizados.

Há duas semanas Blockchain Academy TLV iniciou sua sessão inaugural. A premissa da Academia Blockchain é promover uma discussão técnica ativa e produtiva sobre blocos.

Meu objetivo é explicar o que eu aprendi até agora na minha jornada de blocos de bloco, e acompanhar você através de uma implementação de bloqueio inspirado Ethereum, eu tenho trabalhado nas últimas 2 semanas.

O que não posso criar, não entendo

Durante o primeiro encontro do Blockchain TLV, Leonid Beder discutiu os conceitos básicos do blockchain, e codificou uma implementação de bloqueio básico em formato simples. A implementação incluiu a seguinte funcionalidade:

Blockchain: uma lista crescentemente crescente de registros , denominados blocos , que são vinculados e protegidos usando criptografia . Cada bloco geralmente contém um ponteiro hash como um link para um bloco anterior, um carimbo de data e hora e dados de transação. Definimos uma classe inicial com a seguinte interface:

  • Nós armazenamos todos os blocos na cadeia de blocos.
  • Nós armazenamos o conjunto de todas as transações que esperam ser processadas.
  • Método para criar novos blocos
  • Método para envio de novas transações no pool.

Blocos: Todo bloco da nossa cadeia conterá

  • Número do bloco (ou seja, “3º bloco na cadeia”)
  • transações
  • Timestamp – tempo de criação do bloco
  • Número não-arbitrário que só pode ser usado uma vez
  • O hash do bloco anterior – usando o hash anterior, tornamos a cadeia de blocos imutável

Transações: definimos uma classe de transações que continha

  • O endereço público do remetente
  • O endereço público do destinatário
  • O valor da transação.

Enviar um nó : um bloco é um banco de dados distribuído e descentralizado, onde cada nó da rede possui uma cópia completa do histórico de transações Uma vez que estamos desenvolvendo uma cadeia de bloqueio sem permissões, todos podem participar. Este método nos permite adicionar nós à rede.

Enviar uma transação : um bloco de cadeias serve como registro do histórico de transações. Embora uma transação possa ser definida de forma ampla, o caso de uso mais popular é uma transferência de fundos do usuário A para o usuário B. Esse método nos permite criar transações, esperando ser minado.

Mine a Block : as transações não são refletidas na rede imediatamente. Precisamos investir o poder computacional na validação de transações. Isso é chamado de Prova de Trabalho. Minar um bloco é a ação de executar “Prova de Trabalho” em todas as transações que foram recentemente emitidas, mas ainda não foram validadas. Não há almoços gratuitos em criptografia;)

Consenso : Consenso é o processo de todos os nós que chegam a acordo sobre o estado atual da rede. Escolhemos a abordagem da “Cadeia mais longa” (Greedy Maior Observado Subtree). Esta abordagem afirma que todos os nós aceitarão o bloqueio do nó com a maioria dos blocos. O raciocínio por trás disso, é que a cadeia de blocos mais longa possui o poder mais computacional investido nele (lembre-se, exigimos que os blocos sejam validados via PoW) e, portanto, é o mais confiável / credível.

Confira o código fonte das oficinas aqui.

Embora fosse um monte de material novo para processar em uma hora, fiquei preso 🙂 Para o final da oficina, Leonid anunciou uma surpresa!

                                                            Eu gosto de surpresas

Haveria uma competição para ver quem poderia fazer o pedido de atração mais criativo e “incrível” para o bloco de bloco básico que acabamos de construir.

Meu trabalho nas últimas 2 semanas

Eu estava com vontade de aprender mais sobre blockchain, e acredito que construir um é a melhor maneira de fazer isso. Comecei a criar uma cadeia de blocos inspirada na implementação Ethereum com as seguintes características:

  • Sistema de contabilidade – os usuários poderão registrar contas (contas externas) com um saldo e iniciar transferências de fundos. Além disso, os usuários podem registrar contas de contrato e implantar contratos inteligentes em toda a rede
  • Máquina de estado baseada em transações
  • Transações garantidas e validadas e transições de estados
  • Permita que os usuários escrevam contratos inteligentes e aplicativos descentralizados onde eles podem criar suas próprias regras arbitrárias para propriedade, formatos de transação e funções de transição do estado.

Contas

O estado compartilhado global de nós na rede é composto por contas. As contas detêm informações importantes, como

  • endereço: isso servirá como o nome da conta, semelhante ao que fizemos na oficina.
  • saldo: montante dos fundos de propriedade da conta
  • nonce : se a conta é uma conta de propriedade externa, esse número representa o número de transações enviadas pelo endereço da conta.

Minha implementação de bloqueio tem dois tipos diferentes de contas:

  • Contas externas, que são controladas por chaves privadas (via criptografia RSA)
  • Contas contratuais, que são controladas pelo código do contrato.

Estado compartilhado único em toda a rede

As contas são públicas, e você pode ver qualquer conta, dado seu endereço, e o nó foi registrado. Eu criei contas “globais” informando todos os nós da criação de uma conta na rede. Então, quando as transações da conta são despachadas para um nó, eu propagar essa transação para todos os nós na rede. Desta forma, o bloco é verdadeiramente descentralizado, e não dependemos de nós simples para informações valiosas, como existência de conta ou saldos de contas. Essencialmente, criamos um singular “estado compartilhado” entre os nós.

Registramos cada conta em cada nó, de modo que seja “global”

Diferenças entre contas externas e de contrato

A principal diferença entre os dois tipos de contas está enraizada na forma como eles podem se comunicar com outras contas na rede. Uma conta externa pode se comunicar de duas maneiras

  1. Mensagens de outras contas externas (ou seja, uma transação que move fundos da conta A para B).
  2. Invocando a execução do método em contas contratuais. Esses métodos variam, pois dependem apenas do autor do contrato e do contrato que ele / ela criou.

É importante esclarecer que as contas do contrato, em contraste com as contas externas, não podem enviar despachos explícitos para a rede. Em vez disso, as contas de contrato só podem emitir transações em resposta a outras transações que receberam.

Contas Externas

A autenticação de contas é feita via criptografia RSA. Após a inicialização da conta, um par privado de chave pública é criado e gravado no disco.

Teclas criadas no construtor ExternalAccounts. À direita, vemos a chave pública

Essas chaves são usadas para assinar digitalmente pedidos de transações de saída com as credenciais da conta. Uma implementação mais robusta sempre pede uma conta, quer ele quer ou não assinar o pedido antes de enviá-lo. Você pode ver uma implementação rudimentar deste em requestAuthForTransaction.sh.

requestAuthForTransaction.sh

Um pressuposto que fiz para esta implementação é que todas as contas concordam em assinar todos os pedidos de transações com suas credenciais.

Contas de Contrato

As contas do contrato são controladas pelo seu código. Eles simplesmente executam um código específico quando invocados e têm controle direto sobre o equilíbrio.

Um dos desafios aqui foi descobrir como suportar isso em uma maneira dinâmica, distribuída, descentralizada e de confiança. O Ethereum usa uma máquina virtual acessível a nível mundial (dado um ponteiro para o código de byte do contrato) para executar o código do contrato. Mas JS não tem uma VM globalmente acessível fora da caixa para todos os nós a serem consultados. Inicialmente, tentei implantar um contrato para todos os nós na rede como um objeto JSON com stringência, de modo que a execução do contrato poderia ser invocada de forma independente em cada nó, analisando o objeto recebido. Infelizmente, o JSON.stringify ignora métodos e funções, portanto, eliminando contratos inteligentes de suas funcionalidades em gravações. A minha solução alternativa para o envio de contratos de forma dinâmica (não codificada em cada instância de nó) em toda a rede foi a seguinte:

Implantando um Contrato

  1. Escreva um contrato inteligente como um objeto JS simples.

2. Envolva-o com parênteses para torná-lo uma string e remova todas as novas linhas para que possa ser processado através do método JS eval incorporado quando outros nós a recebem.

3. Envie a string como dados para todos os nós na rede.

Implantando um contrato em toda a rede

Isso permite que os nós criem contratos on-line e os implante na rede. Agora, um nó pode receber um contrato que não conheceu antes e executar seu código! 😀😀😀

Escrevendo atualizações do contrato

Inicialmente, podemos analisar o contrato stringificado usando o método JS eval incorporado, que leva uma seqüência de caracteres e o avalia como uma declaração JS.

Depois de executar um método que altera o estado do contrato (ou seja, altera o saldo do contrato), queremos armazenar o contrato na íntegra, sem perder o acesso aos nossos métodos.

Portanto, usaremos o método de stringis JSON e passamos uma função “substituição” personalizada , instruindo-o sobre como seqüenciar as funções.

No futuro, para ler a versão especialmente rigorosa do contrato, passaremos um “reviver” personalizado para o método JSON.parse.

Emitir transações através da execução do contrato

Algumas mutações contratuais só podem atualizar o estado interno do contrato. Outras execuções de contrato podem “emitir” transações que efetuam o estado da rede. Por exemplo, um contrato que detém fundos (os contratos regem seus próprios fundos) pode enviá-los a um usuário específico após uma determinada condição ser cumprida. Essas transações emitidas são ouvidas e colocadas na fila de mineração, de forma semelhante a outras transações na rede. Eles devem ser validados antes de serem gravados no bloco. O fluxo parece assim:

Uma transação emitida por meio de um pedido de mutação do contrato, anexado ao mempool

Contratos inteligentes com permissões

Chamar um contrato inteligente simplesmente invoca um método que resulta em uma emissão de transação. Os contratos são implantados globalmente e gostaríamos de uma maneira fácil de controlar quem pode invocar métodos de contrato. Gostaríamos de permitir que os usuários criem contratos que suportem permissões de usuários. Por exemplo, em uma eleição, nós só queremos que os usuários elegíveis possam votar (podemos determinar a elegibilidade, no entanto, achamos adequado). Como todas as transações solicitadas são assinadas digitalmente via criptografia RSA pelo solicitante, podemos verificar com segurança o usuário que solicitou a execução do contrato e decidir se ele está ou não autorizado a fazê-lo.

Exemplo DAOVotingContract.ts com permissões

Validação de transação

Durante a primeira oficina, implementamos uma versão bruta das transações. Porque não tínhamos contas, nenhuma forma de identificação e nenhum saldo para atualizar, não tinham significado. Depois de implementar o acima, agora podemos verificar a legalidade, ou “correção” de uma transação solicitada

Função de transição estatal

O white paper da Ethereum descreve um cronograma de cryptocurrency como um sistema de transição do estado, onde o estado é composto pelo status de propriedade da moeda dentro do sistema. Na minha implementação, cada nó possui contas que possuem um saldo específico. Mas como o estado (equilíbrio) muda ao longo do tempo? Ethereum especifica uma Função de Transição de Estado da seguinte forma:

Ilustração do Livro Branco Ethereum

Em nossa implementação, tomaremos uma abordagem semelhante para validar transições de estado. Nós vamos:

  1. Verifique se uma transação adere à estrutura solicitada e possui todos os valores necessários.
  2. Todas as transações têm um SenderNodeId e um SenderAddress. Embora esta seja uma hipótese insegura, para a implementação atual e para a falta de um cliente de usuário apropriado, assumiremos que todas as contas concordam e assinam digitalmente todos os pedidos de transações de saída com suas credenciais. Antes de ser submetido à fila de mineração, verificaremos essa assinatura digital .
  3. Verifique se o nonce corresponde ao nonce na conta do remetente .
blockchain.ts

Depois de verificar a transação através do método stateTransitionValidation , podemos adicionar a transação para a fila de mineração e a minha. É importante notar que essas transações ainda não modificaram o estado da rede . Após o consenso, se essas transações pertencem à cadeia mais longa, e é uma transação que move fundos, validaremos que o remetente tenha um saldo de conta adequado. Um exemplo de filtragem de transações ilegais (o remetente A que envia mais fundos, ele possui) pode ser visto em apropriadoFunds.sh.

apropriadoFunds.sh

Para visualizar este processo:

Exemplo de Contratos

Agora que nosso bloco possui contas, transações validadas e uma maneira de criar e propagar contratos em toda a rede, podemos observar alguns contratos reais. Esses contratos são bastante legais e mostram a flexibilidade e o potencial de criar contratos inteligentes na cadeia de blocos.

Contra-contrato

Para começar as coisas, vejamos um contrato simples que atua como um contador. Toda vez que o método incrementValue do contrato é chamado, incrementaremos o contador. Observe que qualquer pessoa pode invocar este código de contrato.

const CounterContract = {
balance: 0,
counter: 0,
incrementValue: function() {
this.counter++;
},
id: 1,
fromAddress: Alice,
call: function() {
return {
getBalance: this.balance,
getFromAddress: this.fromAddress
};
},
send: function() {
return {
incrementValue: this.incrementValue
};
},
abi: function() {
return {
sendables: this.incrementValue.toString()
};
}
};

Invocamos o código do contrato enviando uma solicitação mutateContract /: CounterContract PUT . Este contrato tem seu próprio estado interno que governa. Quando o incrementValue é chamado, o estado do contrato emite uma transação, solicitando a mutação do estado do contrato. Depois de ser minado, a mutação é escrita na cadeia de blocos, de modo que tenhamos um registro de quem usou o contrato (iniciou o pedido de mutação) e como o contrato foi usado.

Este contrato pode ser executado através do cliente Postman ou executando o script counter_contract.sh no diretório shell-scripts.

Transferir fundos após a data arbitrária Contrato

Um cenário mais realista para um contrato inteligente é transferir fundos da conta A para a conta B. O contrato a seguir é baseado no cenário em que Bob quer transferir 400 moedas para Alice, após uma data arbitrária ter passado. Em vez de usar um serviço de terceiros, ou sistema de custódia, ele pode criar um contrato inteligente que verifica quando a data passou, e iniciar uma transferência de fundos.

const MoveFundsAfterDateContract = {
balance: 400,
expirationDate: new Date(October 13, 2016 11:13:00),
id: 2,
fromAddress: Bob,
call: function() {
return { getBalance: this.balance, getFromAddress: this.fromAddress };
},
send: function() {
return { changeBalance: this.changeBalance };
},
abi: function() {
return { callables: this.call(), sendables: this.send() };
},
moveFunds: function() {
var currentDate = new Date();
if (currentDate > this.expirationDate) {
return {
senderNodeId: B,
senderAddress: Bob,
recipientNodeId: A,
recipientAddress: Alice,
value: 20,
action: TRANSACTION_EXTERNAL_ACCOUNT
};
}
return null;
}
};

Quando o método moveFunds do contrato é invocado, ele verificará a data, verá que passou e transferiu fundos para Alice.

Este contrato pode ser executado através do cliente Postman ou executando o script move_funds_after_data_contract.sh no diretório shell-scripts.

DAO Vote para o contrato de bônus

Este cenário envolve um DAO (organização autônoma descentralizada) que quer dar um bônus a um de seus funcionários. Como este DAO é uma organização completamente justa 😀😀😀, devemos votar em quem é merecedor do bônus.

Mas lembre-se, o blockchain é um livro público! Portanto, no momento em que carregamos para contratar a rede, qualquer pessoa pode vê-lo e fazer chamadas para o código do contrato. Nós gostaríamos de restringir a votação somente aos funcionários da DAO. Como mencionei anteriormente, cada solicitação com credenciais de contas, é assinada digitalmente por essa conta, com sua chave privada. Desta forma, é fácil verificar a verdadeira origem dos eleitores. Então, este contrato tem um campo “autorizadoVoters” que verificaremos contra, sempre que uma conta tentar votar.

const DAOVotingContract = {
balance: 400,
id: 3,
authorizedVoters: [
{ nodeId: A, address: Alice },
{ nodeId: B, address: Eve },
{ nodeId: A, address: Gal Gadot }
],
votes: [
{
nodeId: C,
address: Gal Gadot,
votes: 0
},
{
nodeId: C,
address: Ben Affleck,
votes: 0
}
],
fromAddress: Bob,
candidateA: {
nodeId: C,
address: Gal Gadot
},
candidateB: {
nodeId: A,
address: Selena Gomez
},
call: function() {
return {
getBalance: this.balance,
getFromAddress: this.fromAddress
};
},
send: function() {
return {
moveFunds: this.changeBalance
};
},
moveFunds: function(userData, vote) {
// Check if vote requester is authorized
const authorizedVoterIdx = this.authorizedVoters.findIndex(
user =>
user.nodeId === userData.nodeId && user.address === userData.address
);
if (authorizedVoterIdx === 1) return null;
// Check if candidate requester is voting for exists
const candidateIndex = this.votes.findIndex(
candidate => candidate.address === vote
);
if (candidateIndex === 1) return null;
// Cast Vote and verify users can’t vote twice
this.votes[candidateIndex].votes++;
this.authorizedVoters.splice(authorizedVoterIdx, 1);
// Users still need to cast vote
if (this.authorizedVoters.length > 0) return;
this.votes.sort((voteA, voteB) => voteB.votes voteA.votes);
return {
senderNodeId: B,
senderAddress: Bob,
recipientNodeId: this.votes[0].nodeId,
recipientAddress: this.votes[0].address,
value: 400,
action: TRANSACTION_EXTERNAL_ACCOUNT
};
}
};

Este contrato pode ser executado através do cliente Postman ou executando o script vote_permissions_contract.sh no diretório shell-scripts.

Estes são apenas vários exemplos de contratos inteligentes. A estrutura atual permite que qualquer pessoa faça o upload de qualquer contrato (desde que adira ao formato analisável que estou usando), implante-o na rede em sessão e comece a executá-lo. Podemos criar contratos para eleições, armazenamento de arquivos distribuídos e muito mais.

Conclusão

A programação dessa cadeia de bloqueio de prova de conceito foi um desafio! É apenas a ponta do iceberg em termos de formas de melhorar e garantir. Fui um excelente momento pesquisando os conceitos e aprendendo sobre implementações e mecanismos de cadeias de blocos.

Um grande agradecimento a Leonid Beder pela graciosa introdução do blockchain e aos colaboradores da Kin , Orbs e Samsung Next para organizar a Academia Blockchain .

Você pode verificar minha implementação completa aqui.

Se você quiser continuar a discussão do blockchain, sinta-se à vontade para alcançar o Linkedin .

Por último, se você chegou até aqui, obrigado por ficar com isso 🤗🤗🙌🙌🖖🏼

 

Fonte:  https://hackernoon.com/building-a-blockchain-the-grey-paper-5be456018040

Anúncios

Como implementar o Blockchain em JavaScript

Ouvimos falar sobre Bitcoin, Ethereum além de outras moedas praticamente todos os dias. 2017 afinal, foi o ano dascryptocurrencies.

Nesse post porém, não vou focar em nenhuma dessas moedas digitais. Mas sim na tecnologia por trás delas, que muitas pessoas dizem ser tão revolucionárias quanto a própria internet, o Blockchain.

A ideia é implementar passo-a-passo uma versão simplificada do Blockchain em JavaScript e ir explicando como essa tecnologia disruptiva funciona por baixo dos panos.

Então, continue lendo esse post para aprender:

  • O que é e como funciona o Blockchain
  • Proof of Work?
  • Pra que servem os Blocos
  • O que é Mineração

Introdução

O Blockchain parece uma tecnologia de outro mundo e gera muitas dúvidas. Apesar disso, é algo extremamente fácil de definir:

O Blockchain nada mais é do que um banco de dados aberto e distribuído.

Esse banco de dados é composto de Blocos. E todos esses Blocos são ligados entre si em uma sequência. Daí o nome, Blockchain (cadeia de blocos).

Além disso, esse banco de dados é imutável.
E faz sentido que seja.

Imagina se fosse possível que alguém intencionalmente modificasse sua conta. Agora os 10 Bitcoins que você possui viraram 1.

Blocos

Vamos começar a implementação pela parte mais fácil: os Blocos. A estrutura de um Bloco deve possuir os seguintes campos:

  • index
  • timestamp
  • hash
  • previousHash
  • data

Crédito: https://medium.com/@lhartikk/a-blockchain-in-200-lines-of-code-963cc1cc0e54

index e o timestamp são campos comuns em praticamente todos bancos de dados. O campo data serve principalmente pra guardar transações mas podemos também colocar outras informações. O hash é calculado internamente e serve pra manter a integridade de cada Bloco e a segurança de todo o sistema (como vamos ver no final do post). E por final, o previousHash é o elo de ligação que liga cada Bloco ao seu Bloco anterior.

Com isso, temos a primeira implementação de um Bloco:

const sha256 = require(crypto-js/sha256)
class Block {
constructor(index = 0, previousHash = null, data = Genesis block) {
this.index = index
this.previousHash = previousHash
this.data = data
this.timestamp = new Date()
this.hash = this.generateHash()
}
generateHash() {
return sha256(this.index + this.previousHash + JSON.stringify(this.data) + this.timestamp).toString()
}
}
module.exports = Block
view rawblock.js hosted with ❤ by GitHub

A função generateHash usa a biblioteca externa crypto-js pra gerar o hash seguindo o padrão sha256.

Parece complicado, mas tudo o que você precisa saber é que essa função vai receber uma string como por exemplo:

foo

E vai retornar uma string encriptada:

2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae

Blockchain

Agora que já temos uma versão mínima de um Bloco, já podemos começar a construir o Blockchain, que como falei anteriormente é uma sequência de Blocos ligados entre si.

Com isso, essa é a primeira versão do Blockchain:

const Block = require(./block)
class Blockchain {
constructor() {
this.blocks = [new Block()]
this.index = 1
}
getLastBlock() {
return this.blocks[this.blocks.length 1]
}
addBlock(data) {
const index = this.index
const previousHash = this.getLastBlock().hash
const block = new Block(index, previousHash, data)
this.index++
this.blocks.push(block)
}
}
module.exports = Blockchain
view rawblockchain.js hosted with ❤ by GitHub

No construtor da classe, temos o array de Blocos inicializado já com o Genesis Block (o primeiro bloco criado no registro do Bitcoin). Adicionei também o index para poder incrementar toda vez que um novo Bloco for adicionado no Blockchain.

Além disso duas funções foram criadas:

  • getLastBlock
  • addBlock

A primeira é extremamente simples, ela serve pra pegar o último Bloco que foi criado.

A segunda é uma pouco mais complicada, mas também não é nada de outro mundo. Ela serve pra adicionar novos Blocos ao Blockchain.

Integridade

Apesar de a versão anterior já funcionar razoavelmente bem, precisamos adicionar alguma garantia de que o Blockchain não tenha sido alterado por algum ataque malicioso.

Precisamos adicionar uma nova função para checar a integridade do Blockchain:

isValid() {
for (let i = 1; i < this.blocks.length; i++) {
const currentBlock = this.blocks[i]
const previousBlock = this.blocks[i 1]
if (currentBlock.hash !== currentBlock.generateHash()) {
return false
}
if (currentBlock.index !== previousBlock.index + 1) {
return false
}
if (currentBlock.previousHash !== previousBlock.hash) {
return false
}
}
return true
}

Lembrando que para verificarmos a integridade do Blockchain precisamos garantir três características:

  • hash de cada Bloco foi gerado corretamente
  • index dos Blocos está em sequência
  • Os Blocos estão ligados entre si através dos hashes

Com essa simples função podemos testar se modificações maliciosas foram feitas e se o Blockchain deve ser invalidado:

const Blockchain = require(./blockchain)
const blockchain = new Blockchain()
blockchain.addBlock({ amount: 4 })
blockchain.addBlock({ amount: 50 })
console.log(blockchain.isValid()) // true
blockchain.blocks[1].data.amount = 30000 // ataque malicioso
console.log(blockchain.isValid()) // false

E finalmente com isso já temos uma primeira versão básica e funcional do Blockchain em JavaScript:

const Block = require(./block)
class Blockchain {
constructor() {
this.blocks = [new Block()]
this.index = 1
}
getLastBlock() {
return this.blocks[this.blocks.length 1]
}
addBlock(data) {
const index = this.index
const previousHash = this.getLastBlock().hash
const block = new Block(index, previousHash, data)
this.index++
this.blocks.push(block)
}
isValid() {
for (let i = 1; i < this.blocks.length; i++) {
const currentBlock = this.blocks[i]
const previousBlock = this.blocks[i 1]
if (currentBlock.hash !== currentBlock.generateHash()) {
return false
}
if (currentBlock.index !== previousBlock.index + 1) {
return false
}
if (currentBlock.previousHash !== previousBlock.hash) {
return false
}
}
return true
}
}
module.exports = Blockchain
view rawblockchain.js hosted with ❤ by GitHub

Problemas

Apesar de já termos uma versão inicial funcionando, ainda podemos melhorar bastante a nossa implementação.

Um dos problemas com essa versão atual é que usuários podem criar novos Blocos de forma muito rápida, podendo invalidar o Blockchain, ou coisas ainda piores. Não vou entrar em muitos detalhes dessa particularidade da tecnologia, mas o post abaixo faz um excelente trabalho nesse sentido:

Explaining blockchain — how proof of work enables trustless consensus

Em resumo, precisamos de alguma ferramenta que não permita que usuários possam criar Blocos desenfreadamente.

Proof of Work

O conceito de Proof of Work, como o próprio nome já sugere, é um mecanismo que faz com que um usuário tenha um trabalho computacional significativo ao realizar determinada tarefa.

Essa ferramenta já era utilizada antes do Bitcoin ser inventado para evitar por exemplo spams e ataques DoS.

No Bitcoin, o Proof of Work funciona da seguinte forma: o hash que é gerado automaticamente em cada Bloco deve começar com uma quantidade X de zeros, dependendo da dificuldade geral do sistema.

Por exemplo, se a dificuldade geral do sistema for 1, esse hash é inválido porque não começa com um zero:

a5036427617139d3ad9bf650d74ae43710e36d4f63829b92b807da37c5d38e8d

Porém, esse outro hash é válido porque começa com um zero:

07da8bff6cfea68a3f0a5bafc9b24d07f503e2282db36ffb58d43f9f4857c54b

Sempre que um usuário for criar um novo Bloco, ele vai precisar criar diversos hashes até que um deles tenha a quantidade de zeros no começo fazendo com que a regra geral do sistema seja atendida.

Ah, o nome disso é Mineração.

Lembrando que quanto maior o número de zeros que devem estar no começo do hash, maior o poder computacional necessário para a tarefa.

Dito isso, vamos agora implementar a versão final do Blockchain com a mineração.

Primeiramente vamos alterar os Blocos.

class Block {
constructor(index = 0, previousHash = null, data = Genesis block, difficulty = 1) {
this.index = index
this.previousHash = previousHash
this.data = data
this.timestamp = new Date()
this.difficulty = difficulty
this.nonce = 0
this.mine()
}
/* */
}
view rawblock.js hosted with ❤ by GitHub

No construtor, adicionamos os campos difficulty (dificuldade geral do sistema) e nonce (quantidade de tentativas até que o hash correto seja criado). Além disso, temos também um chamada para a função mine.

mine() {
this.hash = this.generateHash()
while (!(/^0*$/.test(this.hash.substring(0, this.difficulty)))) {
this.nonce++
this.hash = this.generateHash()
}
}
view rawblock.js hosted with ❤ by GitHub

A função mine vai criar hashes até que a quantidade de zeros à esquerda do hash seja atentida.

Lembrando que para que os hashes criados sejam diferentes, devemos adicionar o campo nonce na função generateHash:

generateHash() {
return sha256(this.index + this.previousHash + JSON.stringify(this.data) + this.timestamp + this.nonce).toString()
}
view rawblock.js hosted with ❤ by GitHub

Com isso temos a versão final do Blocos com a mineração:

const sha256 = require(crypto-js/sha256)
class Block {
constructor(index = 0, previousHash = null, data = Genesis block, difficulty = 1) {
this.index = index
this.previousHash = previousHash
this.data = data
this.timestamp = new Date()
this.difficulty = difficulty
this.nonce = 0
this.mine()
}
generateHash() {
return sha256(this.index + this.previousHash + JSON.stringify(this.data) + this.timestamp + this.nonce).toString()
}
mine() {
this.hash = this.generateHash()
while (!(/^0*$/.test(this.hash.substring(0, this.difficulty)))) {
this.nonce++
this.hash = this.generateHash()
}
}
}
module.exports = Block
view rawblock.js hosted with ❤ by GitHub

Agora basta alterarmos o Blockchain para que o campo difficulty seja passado para os Blocos:

const Block = require(./block)
class Blockchain {
constructor(difficulty = 1) {
this.blocks = [new Block()]
this.index = 1
this.difficulty = difficulty
}
getLastBlock() {
return this.blocks[this.blocks.length 1]
}
addBlock(data) {
const index = this.index
const difficulty = this.difficulty
const previousHash = this.getLastBlock().hash
const block = new Block(index, previousHash, data, difficulty)
this.index++
this.blocks.push(block)
}
isValid() {
for (let i = 1; i < this.blocks.length; i++) {
const currentBlock = this.blocks[i]
const previousBlock = this.blocks[i 1]
if (currentBlock.hash !== currentBlock.generateHash()) {
return false
}
if (currentBlock.index !== previousBlock.index + 1) {
return false
}
if (currentBlock.previousHash !== previousBlock.hash) {
return false
}
}
return true
}
}
module.exports = Blockchain
view rawblockchain.js hosted with ❤ by GitHub

E é só isso 🙂

Lembrando que o código está todo no GitHub.

Ah, se você quiser saber mais sobre o Blockchain:

Outras implementações:

Fonte: https://tableless.com.br/como-implementar-blockchain-em-javascript/?utm_source=tablelessRelatedLink

Primeiros passos com MongoDB

O MongoDB é um banco de dados documental (Orientado a documentos) open source que proporciona escalabilidade e flexibilidade ao projeto pois ele aninha os dados em documentos JSON e BSON, com isso se tornam simples as buscas. Nesse post farei uma Introdução ao formato “Javascript Object Notation” (JSON), ao BSON e aos primeiros passos com o MongoDB.

O JSON é um formato leve de troca de dados. Para seres humanos, é simples de ler e escrever e para máquinas, é fácil de interpretar e gerar.Quando se fala em aplicações AJAX, o JSON é mais rápido e mais fácil do que o XML.

Com o formato JSON, sempre teremos objetos de Chave-Valor, onde podemos observar alguns pontos característicos:

– As chaves são do tipo “String”.

– O delimitador entre Chave-Valor é o “:” (dois pontos).

– Cada entrada “Chave-Valor” é separada por “,” (vigula).

– Cada objeto JSON é delimitado por “{}” (Chaves).

Utilizando o exemplo abaixo, explicarei os campos que podem compor o “Valor” dentro de um objeto do formato Json.

 

– O nome do livro e a data de lançamento são do tipo “String”.

– A quantidade de páginas é do tipo numérico.

– O status de publicado é do tipo booleano.

– Já o Gênero está recebendo uma matriz.

OBS: Podemos ter valores dos tipos (string, number, object, array, true, false, null)

No mongoDB como complemento ao JSON, existe o BSON que suporta a incorporação de objetos e matrizes dentro de outros objetos e matrizes, ou seja o MongoDB através do BSON cria índices e compara objetos com expressões de consulta em chaves BSON de nível superior que estão aninhadas, isso significa que o MongoDB oferece aos usuários a simplicidade e a flexibilidade dos documentos JSON, juntamente com a velocidade e a riqueza de um formato binário leve.

Basicamente o BSON nasceu com três vértices principais:

– “Lightweight” (Leveza):

O BSON mantem a sobrecarga no mínimo e isso é importante para qualquer formato de representação de dados, especialmente quando usado na rede.

– “Traversable” (Atravessáveis):

O BSON é projetado para mover-se facilmente. Esta é uma propriedade vital para o MongoDB.

– “Efficient” (Eficiente) :

A Codificação de dados e decodificação do BSON pode ser realizada muito rapidamente na maioria das linguagens devido ao uso de tipos de dados C.

Para maiores informações sobre o BSON, segue o link do bsonspec http://bsonspec.org/

Após esta rápida introdução, vamos instalar e dar os primeiros passos com o MongoDB, nesse exemplo vou fazer a instalação em um CentOS, caso você precise instalar em outra plataforma, deixo o link oficial.

– Instalação no Linux.

– Instalação no Windows.

– Instalação no OS X.

Primeiramente vamos adicionar o repositório do MongoDB.

vim /etc/yum.repos.d/mongodb-org.repo

[mongodb-org-3.4]

name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc

 

Vamos atualizar nossa lista de repositórios.

yum repolist

Instalando o MongoDB.

yum install mongodborg

Habilitando o MongoDB em todo boot.

systemctl enable mongod

Iniciando o serviço do MongoDB.

systemctl restart mongod

Nesse momento já podemos acessar a CLI do MongoDB, utilizando o comando “mongo”.

mongo
MongoDB shell version v3.4.3
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.3
>

Quando acessamos a CLI, nos é mostrado a versão do shell, a string de conexão (mongodb://127.0.0.1:27017) nesse caso localhost e a versão do MongoDB instalado.

OBS: Para limpar a tela, podemos utilizar o “CTRL+L ou cls”

Para termos acesso a uma lista completa de comandos, podemos utilizar o help

 

> help

Vamos listar todos os bancos de dados existentes.

> show dbs
admin 0.000GB
local 0.000GB

 

Por padrão o mongoDB vem com duas bases criadas (local e admin), ambas vazias.

Como o MongoDB é um banco de dados documental, ele não trabalha com tabelas e sim “Collections”, para criarmos as nossas collections precisamos estar dentro de algum banco de dados, para acessamos um banco de dados utilizaremos o comando “use”.

> use livros

 

Percebam que o banco de dados “livros” não existia, quando usamos o comando “use” ele verificou a existência, nesse caso como não existia ele criou automaticamente. Para realizarmos operações de inserção, atualização, leitura e remoção de dados no MongoDB, podemos usar algum script remoto fazendo isso ou podemos executar isso direto no shell. Se executarmos direto no shell, podemos usar uma variável global chamada “db”, essa variável faz referencia ao banco de dados no qual você está conectado, no nosso caso o banco “livros”.

Com esse comando nós vamos fazer uma inserção única em uma collection que ainda não existe.

 

> db.misterios.insertOne({ nome : Ponto de Impacto})
{
acknowledged : true,
insertedId : ObjectId(58ee79afcc3801bb06082423)
}

 

Esse retorno indica duas coisas:

1. A gravação foi reconhecida;

2. Foi gerado um campo único e ele foi atribuído ao documento (todo documento precisa de um _id).

Após isso, a collection “misterios” acabou de ser criada, e possui um documento, para verificar o conteúdo dela, vamos gerar uma listagem completa.

 

1
2
3
> db.misterios.find()
{ “_id” : ObjectId(“58ee79afcc3801bb06082423”), “nome” : “Ponto de Impacto” }

 

Um ponto interessante é que mesmo não passando, o próprio mongo inseriu o campo “_id”, parece ser algo totalmente aleatório, porem segue uma sequencia lógica, é uma string com 12 bytes hexadecimais, como descrito abaixo.

      Data             Mac Address              Pid                 Contador

ObjectId:         _ _ _ _       |           _ _ _            |           _ _         |            _ _ _

Os quatro primeiros campos são criados a partir do segundo atual da máquina, em seguida 3 campos nascem com base no endereço Mac da máquina, depois dois campos surgem do “Process ID” e por último um contador randômico que gera mais 3 bytes.

Farei uma sequencia de posts relacionados a MongoDB, nos posts seguintes, mostrarei outros métodos de inserção e faremos o CRUD utilizando a shell do MongoDB. Espero que esse primeiro post esclareça alguns conceitos do MongoDB e de como ele funciona.

 

 

 

 

Fonte: https://www.fordevops.com/primeiros-passos-com-mongodb/

 

 

Instalação e configuração do MongoDB como serviço do Windows

Olá pessoal. Gostaria de ilustrar através desse tutorial como instalar e configurar o MongoDB como um serviço do Windows.

O MongoDB é um banco de dados NoSQL (Not Only SQL), ou seja, os dados são armazenados em coleções de documentos organizados no formato JSON (Java Script Object Notation); bancos de dados convencionais utilizam tabelas com conjuntos fixos de colunas.

Uma das principais vantagens é a possibilidade de flexibilizar a estrutura do documento. O MongoDB utiliza o conceito Free Schema Design e um documento é independente do outro, mesmo estando na mesma coleção.

Para começar os trabalhos utilizando o MongoDB no Windows, é necessário fazer o download do arquivo .msi no site: https://www.mongodb.com/download-center#community

Após realizar o download, execute o arquivo e instale o MongoDB. Durante o processo de instalação, selecione no wizard a opção customizada. Dessa forma será possível alterar o diretório de instalação dos arquivos.

Em seguida, clique no botão Install, conceda permissões de administrador e aguarde para que o MongoDB seja instalado no diretório selecionado. O MongoDB será instalado no diretório informado e sua estrutura deverá ser parecida com a imagem abaixo:

A pasta bin contém os arquivos executáveis, que são necessários, para configurar o MongoDB como um serviço do Windows. Especificamente o arquivo mongod.exe. Esse arquivo é utilizado para indicar ao MongoDB o caminho dos arquivos com as coleções de dados e logs de atividades.

Para essa tarefa, acesse o diretório onde o MongoDB foi instalado no Windows e crie duas pastas, uma com o nome data e outra como log. A pasta data armazenará os arquivos com as coleções de dados. A pasta log armazenará os arquivos com os registros de atividades realizadas no MongoDB.

Após criar as pastas data e log, acesse o console do sistema operacional e navegue até a pasta bin dentro do diretório de instalação do MongoDB e execute o seguinte comando:

No comando acima, o parâmetro install informa ao sistema operacional que o MongoDB deverá ser configurado como um serviço. O parâmetro dbpath informa qual pasta deverá armazenar as coleções de dados e o parâmetro logpath informa o endereço do arquivo de log de atividades do banco de dados.

Após a execução com sucesso, acesse a guia de serviços do Windows e verifique que um novo serviço chamado MongoDB foi configurado. Em seguida, clique com o botão direito do mouse sobre o serviço e selecione a opção start.

 

O MongoDB está instalado e configurado como um serviço automatizado do Windows. Para verificar as instâncias de banco de dados criadas é necessário acessar o diretório bin via console e digitar o seguinte comando:

Fontehttp://wikiti.com.br/pt/2017/06/19/instalacao-e-configuracao-do-mongodb-como-servico-do-windows/

 

O que é MongoDB e porque usá-lo?

MongoDB é um dos mais populares de banco de dados. E disparado o mais famoso NoSQL no mercado. O mesmo é open-source e escrito em C ++.
Desde fevereiro de 2015, MongoDB ocupa a quarta posição no ranking mundial. Ele foi desenvolvido pela empresa 10gen inicialmente, que é hoje conhecida como MongoDB Inc.
MongoDB é um banco de dados orientado a documentos que armazena dados em documentos JSON com esquema dinâmicoIsso significa que você pode armazenar seus registros sem se preocupar com a estrutura de dados, como o número de campos ou tipos de campos para armazenar valoresOs documentos do MongoDB são semelhantes aos objetos JSON.
MongoDB é um banco de dados multi-plataforma NoSQL, que pode ser executado em Windows, Linux e Mac etc. Ele suporta linguagens de programação mais populares, como C #, Java, PHP, Javascript, NodeJs, Python e muito mais! 

Porque MongoDB?

Como você sabe, RDMS guarda dados em tabelas formatadas e utiliza linguagem de consulta estruturada (SQL)para consulta de banco de dadosRDBMS também tem esquema pré-definido com base nos requisitos e um conjunto de regras para definir as relações entre os campos em tabelas.

Fontehttps://codigosimples.net/2016/03/01/o-que-e-mongodb-e-porque-usa-lo/

Banco de dados NoSQL: Um novo paradigma – Revista SQL Magazine 102

Este artigo tem o objetivo de explicar as principais características dos bancos de dados NoSQL.

De que se trata o artigoEste artigo tem o objetivo de explicar as principais características dos bancos de dados NoSQL. Bancos noSQL se referem a uma classe definida de banco de dados não-relacionais que rompem com uma longa história de banco de dados focados nas propriedades ACID. Para tornar ainda mais clara a diferença trazida por este novo paradigma, este artigo também realiza algumas análises comparativas entre bancos noSQL e relacionais.

Em que situação o tema útil

Conhecer o novo paradigma que vem surgindo na área de banco de dados, noSQL, pode ser considerado muito importante para aqueles que trabalham com banco de dados ou tomadores de decisão da área de tecnologia das organizações. É sempre importante estar atento a novas tecnologias e como elas resolvem problemas provenientes das limitações das tecnologias existentes.

Resumo DevMan

Através deste artigo temos a pretensão de apresentar de forma concisa os fundamentos, características e diferenciais dos bancos de dados NoSQL. Além disso, a autora deste artigo acredita ser de suma importância apresentar os fundamentos relacionados ao Banco de Dados Relacional, assim como realizar diversas comparações entre os dois modelos, para que haja uma melhor compreensão e abstração deste novo paradigma chamado Banco de Dados NoSQL.

A forma como nos comunicamos, trocamos informações e criamos conteúdo mudou muito ao longo dos anos. Estamos vivenciando uma época onde as aplicações Web têm revolucionado o mundo em diversos sentidos e a tendência é que este crescimento habilite a criação de uma série de novas aplicações. O grande volume de dados gerados por estas aplicações Web, aliado com a nova forma de interação com o usuário (dinâmica, eficiente e intuitiva), a escalabilidade sob demanda e a necessidade de um alto grau de disponibilidade, tem fomentado o aparecimento de novos paradigmas e tecnologias.

Todos nós sabemos que o banco de dados relacional tem sido usado há muito tempo em larga escala pelo mundo afora, e desde sua criação, por volta do início dos anos 1970, esse tem sido o tipo de banco de dados mais utilizado em empresas que possuem um intenso volume de dados para serem armazenados [1]. Pensando justamente neste imenso volume de dados que tende a crescer a cada momento, começa a se observar que os bancos de dados relacionais possuem certos fatores limitantes, principalmente quando nos referimos a escalabilidade de um sistema [3]. Este ambiente envolto de limitações que os bancos de dados relacionais têm propiciado instigou o surgimento de outros tipos de modelos alternativos de banco de dados que possam suprir essa necessidade.

Diante de tantas dificuldades que são encontradas à medida que as necessidades surgem, está crescendo uma nova geração de banco de dados que vem ganhando bastante força e espaço, estes são conhecidos como NoSQL (“Not Only SQL”) [4], este é o termo genérico que define um banco de dados não-relacional. Este modelo veio com a proposta de atender e gerenciar os grandes volumes de dados, buscando um alto desempenho e disponibilidade. Neste contexto, neste artigo serão apresentadas características desses bancos de dados e se discute ainda como essas novas soluções podem abordar questões que estão sendo atualmente enfrentadas.

História e característica do banco de dados relacional

O banco de dados relacional surgiu como um sucessor dos modelos hierárquicos de rede. Estas estruturas, por sua vez, foram muito utilizadas nos primeiros sistemas de mainframe. No entanto, devido ao grande número de restrições de relacionar estruturas no mundo real, este modelo foi perdendo força para dar lugar aos bancos de dados relacionais [5]. Este, por último, se tornou o grande padrão para a maioria dos Sistemas Gerenciadores de Banco de Dados (SGBDs). Outro ponto importante a salientar sobre o modelo relacional é a utilização de restrições de integridade que garantem a consistência dos dados em um banco de dados. Estas restrições, em sua grande maioria, são conhecidas como chaves primárias (PRIMARY KEY) e chaves estrangeiras (FOREIGN KEY).

Outra característica que devemos ressaltar no Modelo Relacional é o que chamamos de processo de Normalização. Seu objetivo é a aplicação de uma série de passos com determinadas regras sobre a tabela do banco de dados de forma a garantir o projeto adequado dessas tabelas. Um conceito básico da normalização consiste na separação de dados referentes a elementos distintos em tabelas distintas, associadas através da utilização das chaves. Essas regras permitem um armazenamento consistente e, além disso, um eficiente acesso aos dados, reduzindo redundâncias e diminuindo as chances dos dados se tornarem inconsistentes [7].

Além disso, o modelo relacional começou a adotar uma linguagem para a manipulação e consulta destes dados. Estamos nos referindo ao SQL (Structured Query Language). Criada originalmente pela IBM e inspirada na álgebra relacional, ganhou grande destaque pela facilidade do seu uso, diferenciando-a assim de todas as outras linguagens procedurais da época. Devido a sua grande utilização em 1982, o American National Standard Institute (ANSI) tornou o SQL o padrão oficial de linguagem em ambiente relacional, consolidando assim a sua posição de dominância no modelo relacional [1].

Não é possível falar de SQL sem falar também do SGBD, que se caracteriza como um conjunto de programas que permitem armazenar, modificar e extrair em um banco de dado. Falando mais atentamente sobre o assunto, podemos afirmar que o SGBD oferece aos seus usuários processos de validação, recuperação de falhas, segurança, otimização de consultas, garantia de integridade dos dados, entre outros [8].

Além disso, os SGBDs Relacionais oferecem a possibilidade de vários usuários acessarem e manipularem um mesmo banco de dados simultaneamente e principalmente de forma eficiente, algo que é fundamental em sistemas de grande porte.

Os SGBDs relacionais ainda possuem a possibilidade do sistema se recuperar adequadamente de possíveis falhas, ou seja, ele tem a capacidade de voltar ao ponto anterior em que ocorreu a falha, permitindo assim um banco de dados mais consistente.

Vale ressaltar ainda que os bancos de dados relacionais seguem o modelo ACID para preservar a integridade de uma transação. Este conjunto de procedimentos é dividido em quatro propriedades, e são elas:

• Atomicidade: As ações que compõe a ação da transação devem ser concluídas com sucesso para ser efetivada. Se esta transação falhar, será feito o rollback.

• Consistência: Todas as regras/restrições descritas no banco de dados devem ser obedecidas garantindo que o banco de dados passe de uma forma consistente para outra forma consistente.

• Isolamento: Neste caso, a propriedade de isolamento garante que a transição não será interferida por nenhuma outra transação concorrente.

• Durabilidade: Os resultados de uma transação são permanentes, ou seja, o que foi salvo não será mais perdido.

Todos esses diferentes recursos auxiliaram a manter os SGBDs Relacionais sempre em uma posição de predominância entre os mais diversos tipos de ambientes computacionais, mas ao mesmo tempo, não impediu o aparecimento de determinados problemas, isso devido ao grande crescimento do volume de dados presente nos bancos de dados de algumas organizações.

Limitações dos bancos de dados relacionais

Nos dias de hoje, o volume de dados de certas organizações, como podemos citar o caso do Facebook, que atingiu o nível de petabytes (em 2011 este volume de dados ultrapassou 30 petabytes (30 mil terabytes), sendo que menos de um ano antes o volume era de 20 petabytes). Este é um exemplo real de como esse crescimento de dados tem expandido rapidamente [11]. No caso destes tipos de organizações, a utilização dos SGBDs relacionais tem se mostrado muito problemática e não tão eficiente.

Os principais problemas encontrados com a utilização do Modelo Relacional estão principalmente na dificuldade de conciliar o tipo de modelo com a demanda da escalabilidade que está cada vez mais frequente.

Podemos tomar como exemplo o próprio Facebook. Digamos que se o sistema está rodando sobre um SGBD relacional e houver um crescimento do número de usuários, consequentemente haverá uma queda de performance. E para superar este problema seria necessário fazer um upgrade no servidor ou aumentar o número de servidores.

Se o número de usuários continuasse a crescer intensamente, tais soluções apresentadas não se mostrariam suficientes, pois o problema passa a se concentrar no acesso à base de dados. Neste caso, o que poderia ser feito para resolver este problema de escalabilidade seria aumentar o poder do servidor, aumentando sua memória, processador e armazenamento. Este tipo de solução é chamado de Escalabilidade Vertical. Por outro lado, poderíamos aumentar o número de máquinas no servidor web, chamamos esta alternativa de Escalabilidade Horizontal [13].

Vamos citar novamente o Facebook, onde suas aplicações continuam sempre a crescer, chega um momento em que o banco de dados não consegue atender todas as requisições em um tempo hábil. Neste momento poderíamos apelar para a Escalabilidade Vertical e fazer o upgrade na máquina em que está rodando o banco de dados. No entanto, chega um momento em que a capacidade da máquina chega ao limite do orçamento para conseguir uma máquina realmente eficiente. Dessa forma, o próximo passo seria utilizar a Escalabilidade Horizontal, ou seja, colocar mais máquinas rodando o banco de dados. Tal tarefa pode parecer simples, porém, no momento em que escalonamos o banco em diversas máquinas é necessário realizar na grande maioria das vezes uma série de configurações e alterações nas aplicações para que tudo funcione como esperado na nova arquitetura distribuída.

Ainda no campo dos exemplos, vamos imaginar um sistema fictício, e que não se sabe ao certo os campos de determinada entidade, agora imagine este mesmo sistema do dia para a noite sendo acessado por milhares e milhares de pessoas. No outro dia, ao observar sua caixa de email você percebe que diversos usuários possuem ideias realmente inovadoras, porém, para implementar essas ideias no seu sistema é necessário que o banco de dados praticamente por inteiro seja refatorado, afinal, será necessário realizar diversas mudanças estruturais na base de dados . Com este problema em mãos podemos perceber que o Modelo Relacional está focado nos relacionamentos entre as entidades e que isso, por muitas vezes, torna mais “burocrática” a implementação de novas funcionalidades, além dos problemas voltados para a escalabilidade que já havíamos falado, quando há um acesso muito grande de usuários ao sistema.

Como esse intenso volume de dados vem aumentando e pela sua natureza estrutural, os desenvolvedores perceberam a dificuldade ao se organizar dados no Modelo Relacional. É neste ponto que o foco das soluções não-relacionadas está direcionado.

Um novo paradigma: Banco de Dados NoSQL

Pensando em solucionar diversos problemas relacionados à escalabilidade, performance e disponibilidade, projetistas do NoSQL promoveram uma alternativa de alto armazenamento com velocidade e grande disponibilidade, procurando se livrar de certas regras e estruturas que norteiam o Modelo Relacional. Se por um lado havia um rompimento das regras do Modelo Relacional, por outro lado havia ganho de performance, flexibilizando os sistemas de banco de dados para as diversas características que são peculiares de cada empresa. Esta flexibilidade passou a se tornar fundamental para suprir os requisitos de alta escalabilidade necessários para gerenciar grandes quantidades de dados, assim como para garantir uma alta disponibilidade destes, característica fundamental para as aplicações Web 2.0. Algumas grandes organizações passaram a investir em seus próprios SGBDs baseando-se na ideia do NoSQL.

O termo NoSQL foi inicialmente utilizado em 1998 a partir de uma solução que não oferecia uma interface SQL, mas este sistema tinha como base o Modelo Relacional. Futuramente, o modelo passou a representar determinadas soluções que se tornavam melhores que a utilização do Modelo Relacional, desde então passou a utilizar a abreviação Not Only SQL (Não apenas SQL) [13]. A proposta dos bancos NoSQL na realidade não é extinguir o Modelo Relacional, mas utilizá-lo em casos onde é necessária uma maior flexibilidade na estruturação do banco.

Este movimento está bastante enraizado no open source. E apesar de existirem muitos bancos de dados nesta categoria, o movimento passou a ganhar mais força quando determinadas empresas consideradas gigantes da tecnologia passaram a utilizar suas próprias implementações proprietárias [14]. Neste caso, podemos citar o Google, que desde 2004 investe no BigTable que foi desenvolvido para suprir as necessidades de armazenamento da empresa, baseado na filosofia do alto desempenho, escalabilidade e disponibilidade [15]. Além disso, temos também o famoso Cassandra, desenvolvido pelo Facebook para lidar com o grande fluxo de informações [16]. Em 2010 o Cassandra mostrou ser um banco de dados consolidado e passou a ser utilizado pelo Twitter, que utilizava o MySQL anteriormente [17].

Temos ainda o Apache CouchDB, que é um banco de dados open source orientado a documentos que projetado especialmente para suportar computação distribuída em larga escala [18].

Apesar da nomenclatura de todos esses bancos de dados serem NoSQL, eles não são completamente iguais, possuem na verdade muitas características semelhantes e muitas particularidades que os diferenciam.

Principais características dos Bancos de Dados NoSQL

Os bancos de dados NoSQL apresentam determinadas características que considero importantes de serem consideradas neste artigo, além disso, são essas características que os tornam tão diferentes dos bancos de dados relacionais. Algumas dessas características são:

• Escalabilidade Horizontal: na medida em que o volume de dados cresce, aumenta-se a necessidade de escalabilidade e melhoria do desempenho. Dentre todas as possibilidades para esta solução, a escalabilidade horizontal se torna a mais viável, porém requer diversas threads ou que processos de um tarefa sejam criadas e distribuídas. Dessa forma, o uso de um banco de dados relacional poderia ser muito complexo. Não queremos dizer que os bancos de dados relacionais não escalam, a verdade é que eles não escalam facilmente. Isto por que no momento em que diversos processos se conectam simultaneamente em um mesmo conjunto de dados há uma geração de uma alta concorrência aumentando assim o tempo de acesso às tabelas. Neste contexto, uma grande vantagem dos bancos NoSQL é justamente a ausência de bloqueios, o que permite a escalabilidade horizontal com uma maior facilidade e eficiência (ele não é afetado pelo aumento da concorrência). Uma alternativa muito utilizada para alcançar a escalabilidade horizontal é o Sharding, que divide os dados em múltiplas tabelas a serem armazenadas ao longo de diversos nós na rede. O que esta técnica faz, na realidade, é romper a cadeia de relacionamentos, que é uma forte característica nos bancos relacionais. É possível realizar o Sharding em banco de dados relacionais de forma manual. Entretanto, esta não é uma tarefa simples e demonstra complexidade de implementação para a equipe que está desenvolvendo [12].

• Ausência de esquema (Schema-free) ou esquema flexível: Outra característica notável em bancos de dados NoSQL é a ausência parcial ou total de esquema que define a estrutura de dados. É justamente essa ausência de esquema que facilita uma alta escalabilidade e alta disponibilidade, mas em contrapartida não há a garantia de integridade dos dados, fato este que não ocorre no Modelo Relacional [20].

• Suporte nativo a replicaçãoEsta é outra forma de prover a escalabilidade, pois, no momento em que permitimos a replicação de forma nativa o tempo gasto para recuperar informações é reduzido [21].

• API simples para acessar o banco de dados: Em banco de dados NoSQL, o foco não está no armazenamento dos dados e sim como recuperar estes dados de forma eficiente. Pensando nisso, é fundamental APIs desenvolvidas para facilitar o acesso às devidas informações para que se possa usar o banco de dados de forma rápida e eficiente.

• Consistência eventual: Outra característica particular de bancos NoSQL é que nem sempre a consistência dos dados é mantida. Esta característica tem embasamento no teorema CAP (Consistency, Availability e Partition tolerance) que afirma que em um dado momento só é possível garantir duas destas três propriedades, que seriam Consistência, Disponibilidade e tolerância à partição [32]. No mundo real, normalmente estas duas últimas são privilegiadas. Como consequência disto, as propriedades do ACID não são respeitadas simultaneamente, ao contrário disto, temos outro conjunto de projetos denominado BASE (Basicamente disponível, Estado leve e consistente em momento indeterminado) [21]. Ou seja, é necessário haver um planejamento para que o sistema possa tolerar inconsistências temporárias com o objetivo de priorizar a disponibilidade.

Agora que falamos brevemente sobre as principais características nos bancos de dados NoSQL, é importante ressaltar algumas técnicas utilizadas para a implementação de suas funcionalidades. Entre elas estão:

• Map/reduce: permite a manipulação de enormes volumes de dados ao longo de nós em uma rede [23]. Funciona da seguinte forma: na fase map, os problemas são particionados em pequenos problemas que são distribuídos em outros nós na rede. Quando chegam à fase reduce, esses pequenos problemas são resolvidos em cada nó filho e o resultado é passado para o pai, que sendo ele consequentemente filho, repassaria para o seu, até chegar à raiz do problema.

• Consistent hashing: suporta mecanismos de armazenamento e recuperação, onde a quantidade de sites está em constante mudança [24]. É interessante usar essa técnica, pois ela evita que haja uma grande migração de dados entre estes sites, que podem ser alocados ou desalocados para a distribuição dos dados.

• MVCC (Multiversion concurrency control): Oferece suporte a transações paralelas em banco de dados. Por não fazer uso de locks para controle de concorrência, faz com que transações de escrita e leitura sejam feitas simultaneamente [25].

• Vector clocks: Ordenam eventos que ocorreram em um sistema. Como existe a possibilidade de várias operações estarem acontecendo simultaneamente, o uso de um log de operações informando suas datas se faz importante para informar qual versão de um dado é a mais atual [21].

Modelos de banco de dados NoSQL

Neste caso, temos quatro categorias do NoSQL que as diferenciam entre si:

• Chave-valor (key-value): Este modelo é considerado simples e permite a sua visualização através de uma tabela de hash, no qual há uma chave única e um indicador de determinado dado, podendo ser uma String ou um binário [27]. A Figura 1 apresenta um exemplo que armazena informações com estas características. A chave representa um campo como nome e idade e o valor representam os campos preenchidos com Mara Rúbia e 43, ou seja, a instância para o campo correspondente. Este modelo é caracterizado pela sua facilidade ao ser implementado, permitindo que os dados sejam acessados rapidamente através da chave, aumentando também a disponibilidade do acesso aos dados. Para manipulá-los, utilizamos comandos simples como get() e set(), que retornam e capturam valores. Um problema enfrentado por este tipo de banco de dados é que o mesmo não permite a recuperação de objetos através de consultas mais complexas. Como exemplo, podemos citar o Dynamo que foi desenvolvido pela Amazon como solução de alta disponibilidade para suas necessidades [28].

Figura 1. Campos e informações

• Banco de Dados Orientado a Documento: Como o próprio nome sugere, este modelo armazena coleções e documentos. Explicando melhor, um documento, no geral, é um objeto identificador único e um conjunto de campos que podem ser strings, listas ou documentos aninhados [27]. Diferente do banco de dados chave-valor onde se cria uma única tabela hash, neste modelo temos um agrupamento de documentos sendo que em cada um destes documentos temos um conjunto de campos e o valor deste campo. Neste modelo temos ausência de esquema pré-definido (schema free). Isto significa que é possível que haja atualizações no documento, com a adição de novos campos, por exemplo, sem afetar adversamente outros documentos. Outra característica interessante é que não é necessário armazenar valores de dados vazios para campos que não possuem um valor. Na Figura 2 temos o exemplo de um determinado documento que foi definido por: Assunto, Autor, Data, Tags e Mensagens. Caso eu deseje implementar outro campo chamado “Minha opinião sobre o site:”, não haverá nenhum tipo de restrição ou complexidade de inserir tal dado no banco de dados, esta flexibilidade é um ponto forte neste tipo de modelo. Como exemplo de sistema de banco de dados que utiliza este tipo de solução destacamos o CouchDB e o MongoDB. O CouchDB utiliza o formato JSON e é implementado em Java. Já o mongo é implementado em C++ e permite tanto concorrência quanto replicação.

Figura 2. Documento com informações

• Orientado a Coluna (column family): Demonstra maior complexidade que o de chave-valor. Este tipo de banco de dados foi criado para armazenar e processar uma grande quantidade de dados distribuídos em diversas máquinas. Aqui existem as chaves, mas neste caso, elas apontam para atributos ou colunas múltiplas. Neste caso, os dados são indexados por uma tripla (coluna, linha e timestamp), a coluna e linha são identificadas por chaves e o timestamp permite diferenciar múltiplas versões de um mesmo dado [14]. Como o próprio nome sugere, as colunas são organizadas por família da coluna. Vale destacar que as operações de escrita e leitura são atômicas, ou seja, os valores associados a uma linha são considerados em sua execução, independente das colunas que estão sendo lidas/escritas. O conceito associado a este modelo é o de família de colunas, com o objetivo de reunir colunas que armazenam o mesmo tipo de informação. Como exemplo, a Figura 3 modela o conceito de amigos, onde o primeiroNome e sobrenome são colunas pertencentes à família de colunas denominada “nome”. Da mesma forma, as colunas endereço, cidade e estado pertencem à família local. É interessante observar que na linha 001 a pessoa Mara tem diversos endereços. Como a busca neste tipo de banco de dados é atômica, mesmo que o interesse seja buscar o primeiroNome da linha 001, todas as colunas serão retornadas quando esta mesma linha for consultada. Este modelo permite ainda o particionamento de dados, oferecendo forte consistência, no entanto, a alta disponibilidade é o seu ponto fraco. Este modelo de dados surgiu com o BigTable criado pelo Google [15]. Além do BigTable temos também o Cassandra que foi desenvolvido pelo Facebook [16].

Figura 3. Representação de amigos

• Orientado a Grafos: este modelo possui três componentes básicos: nós (vértices dos grafos), os relacionamentos (arestas) e as propriedades (conhecidos também como atributos). Este modelo é visto como multigrafo rotulado e direcionado, onde cada par de nós pode ser conectado por mais de uma aresta. A utilização deste modelo é muito útil quando é necessário fazer consultas demasiadamente complexas. O modelo orientado a grafos possui uma alta performance, permitindo um bom desempenho nas aplicações [27]. Para exemplificar o que foi dito, podemos analisar a Figura 4 que representa uma aplicação que mantêm informações relativas à viagem. Uma consulta pertinente seria: “Quais cidades foram visitadas anteriormente por pessoas que foram para Nova Iorque?”. No modelo de banco de dados relacional tal consulta poderia se mostrar complexa, pois não permitem que os dados sejam representados de uma forma natural.

Como exemplo, podemos citar o Neo4j que é um banco de dados open source. O Neo4J trata-se de um banco de dados baseado em grafos desenvolvido em Java. Além de possuir suporte completo para transactions, ele também trabalha com nós e relacionamentos. Ainda no exemplo da Figura 4, temos diversas pessoas: João, Ricardo, Carolina, Maria, Fernando e Fábio que representam nós do grafo e estão conectadas a cidades que visitaram ou residiram. Por exemplo: Ricardo viajou para Roma e Bruxelas e já residiu em Toronto e Paris. A partir de cada cidade, precisamos dos relacionamentos de entrada que também sejam do tipo “viajou” e com isso encontramos pessoas que viajaram para o mesmo lugar que Ricardo, neste caso, Carolina e Fernando.

Figura 4.Nós do grafo

Levando em consideração tudo o que foi dito, é fundamental ressaltar que nenhum modelo é superior a outro. Na realidade, o que ocorre é que um modelo pode ser mais adequado para ser utilizado em certas situações. Por exemplo, para a utilização de um banco de dados de manipulação de dados que frequentemente serão escritos, mas não lidos (um contador de hits na Web, por exemplo), pode ser usado um banco de dados orientado a documento como o MongoDB. Já aplicativos que demandam alta disponibilidade, onde a minimização da atividade é essencial, podemos utilizar um modelo orientado a colunas como o Cassandra. Aplicações que exigem um alto desempenho em consultas com muitos agrupamentos podem utilizar um modelo orientado a grafos.

O importante é que no momento da criação do aplicativo os desenvolvedores utilizem a melhor solução que se encaixa no perfil desejado. Utilizar a solução adequada ao criar o banco de dados significa uma diminuição dos custos para a sua criação, assim como um banco eficiente no processamento de dados do ponto de vista das suas necessidades.

Principais diferenças entre SGBDs Relacionais e NoSQL

A partir do momento em que se pensa na possibilidade de utilizar um banco de dados NoSQL ao invés de um modelo relacional, é preciso levar algumas questões em consideração, como critérios de escalonamento, consistência e disponibilidade de dados. Vamos apresentar algumas discussões comparativas mais marcantes no que se diz respeito a estes três conceitos.

Falar sobre escalabilidade é essencial porque é neste aspecto que os bancos de dados NoSQL possuem uma grande vantagem em relação aos SGBDs tradicionais, basicamente por terem sido criados para essa finalidade. Os bancos de dados relacionais possuem uma estruturação que não a permite tanta flexibilidade, além disso, é menos adaptada para situações em que o escalonamento se faz necessário.

Para alcançar uma melhor escalabilidade, os bancos de dados relacionais utilizam o recurso da escalabilidade vertical (scale up) que tem como característica a simplicidade de sua implementação e esta tem sido a forma mais indicada para se realizar o escalonamento do banco de dados. A partir do momento em que uma aplicação está sendo demasiadamente acessada por um número muito grande de usuários, este tipo de escalonamento passa a não ser mais suficiente. O próximo passo consiste em escalonar o próprio banco de dados, que consiste basicamente em distribuir o banco em várias máquinas, particionando os dados. Conhecido também como sharding ou escalonamento horizontal. Esse tipo de escalonamento se mostra muito complexo ao ser implementado em um SGBD relacional devido à dificuldade em se adaptar a toda estrutura lógica do Modelo Relacional, primeiro porque os SGBDs relacionais obedecem aos critérios de normalização e o processo de sharding vai contra a tudo isso, pois se caracteriza pela desnomarlização dos dados. Segundo ponto, há uma mudança de paradigma em relação ao processo de escalonamento. Enquando SGBDs tradicionais trabalham para reforçar o servidor, o sharding tem como objetivo trabalhar com o escalonamento horizontal, distribuindo seus dados em diversos setores. Terceiro ponto, o volume de dados por máquina é minimizado devido a esta distribuição, afinal, conjunto de dados menores são mais simples de serem gerenciados, acessados e atualizados. Por último, a disponibilidade do sistema é otimizada em relação ao modelo relacional, pelo fato de que se houver a queda do sistema em uma máquina não irá causar a interrupção do mesmo.

Esta questão da disponibilidade demonstra muita preocupação em determinadas organizações. Podemos citar um evento que ocorreu em 2008, em que a rede social Twitter ficou fora do ar durante 84 horas, neste evento o Twitter ainda utilizava o PostgreSQL, sendo considerada a rede social mais instável daquele ano [30]. A partir de 2009, quando começou a utilizar o Cassandra, outro evento similar ocorreu, porém o site ficou fora dor ar durante 23 horas e 45 minutos [17].

Neste quesito, o banco de dados NoSQL se destaca pela maior disponibilidade, maior rapidez nas consultas, paralelismo de atualização de dados e maior grau de concorrência.

Os bancos de dados NoSQL foram projetados para este fim, e da forma mais simples e natural possível. Como exemplo podemos citar o MongoDB que inclui um módulo de sharding automático que permite a construção de um cluster de banco de dados escalado horizontalmente para, dessa forma, incorporar novas máquinas de forma dinâmica [19].

Outra coisa que devemos notar ao fazer a comparação de uma banco de dados relacional e NoSQL é no que se refere ao controle de concorrência. Se por um lado, no Modelo Relacional utilizamos locks para garantir que dois usuários não acessem o mesmo item simultaneamente, no banco de dados NoSQL utilizam-se outras estratégias que acabam por permitir um maior grau de concorrência. Para citar uma dessas estratégias podemos citar como exemplo o banco de dados CouchDB que utiliza o MMVC. A ideia principal é criar diversas versões dos documentos e permitir a atualização sobre uma dessas versões mantendo ainda a versão desatualizada. Agindo dessa forma não há a necessidade de bloquear os itens dos dados.

Ao se pensar em substituir um banco de dados relacional por um NoSQL, a arquitetura fica vulnerável à perda de consistência, porém, pode-se ganhar em flexibilidade, disponibilidade e performance. Outra coisa interessante para ser destacada são as diferenças de paradigmas utilizadas no Modelo Relacional e nos bancos NoSQL. No que diz respeito a este primeiro, temos o ACID que força a consistência ao final de cada operação, já o paradigma BASE, que é utilizado comumente pelo segundo, permite que o banco de dados eventualmente seja consistente, ou seja, o sistema só torna-se consistente no seu devido momento.

Para compreendermos melhor todas essas diferenças, observe a Tabela 1 que exemplifica de forma concisa alguns dos conceitos descritos neste artigo.

Banco de Dados Relacional Banco de Dados NoSQL
Escalonamento É importante lembrar que é possível ser feito o escalonamento em um Modelo Relacional, no entanto, é muito complexo. Possui uma natureza estruturada, portanto, a inserção dinâmica e transparente de novos nós a tabela não é realizada naturalmente. Não possui um esquema pré-definido fazendo com que este tipo de modelo seja flexível o que favorece a inserção transparente de outros elementos.
Consistência Neste quesito, o Modelo Relacional se mostra forte. As suas regras de consistência são bastante rigorosas no que diz respeito à consistência das informações. É realizada eventualmente no modelo: tem apenas a garantia que se não houver nenhuma atualização nos dados, todos os acessos aos itens devolverão o último valor que foi atualizado.
Disponibilidade Por não conseguir trabalhar de forma eficiente com a distribuição de dados, o Modelo Relacional acaba não suportando uma demanda muito grande de informações. Outro ponto forte neste modelo é o que diz respeito à disponibilidade, pois possui um alto nível de distribuição de dados, permitindo assim que seja possível fazer com que um enorme fluxo de solicitações aos dados seja atendido com a vantagem do sistema ficar indisponível o menor tempo possível.

Tabela 1. Análise comparativa entre Banco de Dados Relacional e NoSQL

Conclusão

Com o grande crescimento do volume de dados em determinadas organizações, os bancos de dados NoSQL tem se tornado uma grande alternativa quando nos referimos a escalabilidade e disponibilidade, fatores estes que se tornam imprescindíveis em algumas aplicações Web.

Para realizar a migração de um SGBD Relacional para um banco de dados NoSQL é preciso levar diversos fatores em consideração. A empresa em questão deve mensurar as diversas vantagens e desvantagens propostas por ambos os modelos, e estes critérios de comparação são dos mais diversos tipos, indo desde a escalabilidade do sistema, passando por avaliação sobre consistência de dados e quão importante é a disponibilidade do banco de dados para o sistema.

Em relação a bancos de dados relacionais, sabemos da sua “experiência” no mercado, no qual é utilizado em larga escala. Além disso, sabemos da solidez de suas soluções que são mais maduras e experimentadas. Enquanto isso, os bancos de dados NoSQL ainda estão conquistando seu espaço no mercado e definindo os seus próprios padrões. Além disso, sabemos que para diversas organizações a consistência de dados se torna um fator determinante e as transações através dos SGBDs Relacionais são a melhor alternativa para lidar com esse problema.

Por outro lado, temos o problema do grande volume de dados enfrentado por diversas empresas, assim como a necessidade que estes sistemas estejam disponíveis para os seus usuários. Nestas situações, os bancos de dados NoSQL acrescentam diversos pontos positivos, primeiro pela sua possibilidade de escalonamento e pela simplicidade do seu modelo, onde não há esquemas pré-definidos, e segundo pela existência de uma grande distribuição de dados, oferecendo assim um maior suporte de solicitações a estes dados para serem atingidos. Adicionalmente, é importante ressaltar que uma escalabilidade em alto grau se faz necessária a empresas que utilizam um banco de dados de grande porte e onde a disponibilidade é um fator decisivo. Acredito que a utilização de um banco de dados NoSQL onde a escalabilidade e a disponibilidade não se demonstre determinante, ainda é algo que é necessário discutir.

Neste sentido, este artigo teve a finalidade de explicar as principais características dos bancos de dados NoSQL e de forma mais concisa o banco de dados Relacional, assim como realizar algumas análises comparativas entre estes dois modelos que atualmente disputam e complementam o mercado. Ressaltando que não existe um banco de dados superior ao outro, a decisão do uso de cada um se refere à necessidade que a empresa está enfrentando.

Referências1. http://www.jornaltemporeal.com/2010/06/10/o-crescimento-da-internet-o-avanco-da-tecnologia-pelo-mundo/

2. http://nosql-database.org/

3. http://uniredes.org/kb/?View=entry&EntryID=224

4. http://www.ime.usp.br/~andrers/aulas/bd2005-1/aula11.html

5. http://www.dicasparacomputador.com/pesquisa-revela-que-empresas-tem-dificuldade-administrar-grandes-volumes-dados.

6. http://www.infoq.com/br/news/2011/08/facebook-maior-migracao.

7. http://escalabilidade.com/2010/03/08/introducao-ao-nosql-parte-i/.

8. http://blog.caelum.com.br/bancos-de-dados-nao-relacionais-e-o-movimento-nosql/

9. F. Chang , J. Dean , S. Ghemawat , W. C. Hsieh , D. A. Wallach , M. Burrows , T. Chandra , A. Fikes , R. E. Gruber, “Bigtable: A distributed storage system for structured data”, In Proceedings of the 7th Conference on Usenix Symposium on Operating Systems Design And Implementation, Volume 7, 2006.

10. Lakshman, P. Malik, “Cassandra – A Decentralized Structured Storage System”, LADIS 2009.

11. http://computerworld.uol.com.br/tecnologia/2010/02/23/crescimento-faz-twitter-trocar-o mysql-pelo-cassandra/.

12. J. C. Anderson, N. Slater, J. Lehnardt,, “CouchDB: The Definitive Guide”, 1ª edição, O’Reilly Media, 2009.

13. http://www.mongodb.org/.

14. http://www.igvita.com/2010/03/01/schema-free-mysql-vs-nosql/.

15. http://dbpedias.com/wiki/NoSQL:Consistency_Models_in_Non-Relational_Databases.

16. http://ccsl.ime.usp.br/wiki/images/2/20/NoSQL_Vantagens_Desvantagens_e_Compromissos.pdf.

17. http://www.nosqldatabases.com/main/tag/consistent-hashing.

18. http://dbpedias.com/wiki/NoSQL:Consistency_Models_in_Non-Relational_Databases.

19. https://www.ibm.com/developerworks/mydeveloperworks/blogs/fd26864d-cb41-49cf-b719-d89c6b072893/entry/escolhendo_a_ferramenta_certa_para_o_banco_de_dados_nosql1?lang=en.

20. http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html.

21. http://nosqlba.com.br/.

22. http://idgnow.uol.com.br/internet/2009/02/19/twitter-e-o-servico-social-mais-instavel durante-2008-aponta-estudo/.

23. http://www.ffb.edu.br/sites/default/files/tcc-20102-gleidson-sobreira-leite.pdf .

24. W. Vogels, “Eventually Consistent”, Scalable Web Services, Volume 6 No. 6, Outubro de 2008.

Fonte: https://www.devmedia.com.br/banco-de-dados-nosql-um-novo-paradigma-revista-sql-magazine-102/25918

SQL em PL / SQL

Neste tutorial, vamos aprender como usar o SQL em PL / SQL. O SQL é o componente atual que cuida da busca e atualização de dados no banco de dados, ao passo que PL / SQL é o componente que processa esses dados. Além disso, neste artigo, também discutiremos como combinar o SQL no bloco PL / SQL.

 

Neste tutorial, você aprenderá –

Transações DML em PL / SQL

CURSOR Concept em PL / SQL

Atributos do cursor

FOR Loop Cursor statement

BULK COLLECT em PL / SQL

Declarações TCL em PL / SQL

Transação Autônoma

Transações DML em PL / SQL

DML significa Idioma de Manipulação de Dados . Essas declarações são usadas principalmente para realizar a atividade de manipulação. Trata-se basicamente das operações abaixo.

Inserção de dados

Atualização de dados

Eliminação de dados

Projeção de dados / busca

Em PL / SQL, podemos fazer a manipulação de dados somente usando os comandos SQL.

Inserção de dados

Em PL / SQL, podemos inserir os dados em qualquer tabela usando o comando SQL INSERT INTO. Este comando levará o nome da tabela, a coluna da tabela e os valores das colunas como a entrada e insira o valor na tabela base.

O comando INSERT também pode levar os valores diretamente de outra tabela usando a instrução ‘SELECT’ ao invés de dar os valores para cada coluna. Através da instrução “SELECT”, podemos inserir tantas linhas como a tabela base contém.

SQL em PL / SQL

Sintaxe Explicação:

A sintaxe acima mostra o comando INSERT INTO. O nome e os valores da tabela são campos obrigatórios, enquanto os nomes das colunas não são obrigatórios se as instruções do inserto tiverem valores para toda a coluna da tabela.

A palavra-chave ‘VALORES’ é obrigatória se os valores forem dados separadamente, como mostrado acima.

SQL em PL / SQL

Sintaxe Explicação:

A sintaxe acima mostra o comando INSERT INTO que leva os valores diretamente do <table_name2> usando o comando SELECT.

A palavra-chave “VALORES” não deve estar presente neste caso, pois os valores não são fornecidos separadamente.

Atualização de dados

Atualização de dados simplesmente significa uma atualização do valor de qualquer coluna na tabela. Isso pode ser feito usando a instrução ‘UPDATE’. Esta declaração leva o nome da tabela, o nome da coluna e o valor como entrada e atualiza os dados.

SQL em PL / SQL

Sintaxe Explicação:

A sintaxe acima mostra a UPDATE. A palavra-chave ‘SET’ instrui esse mecanismo PL / SQL para atualizar o valor da coluna com o valor fornecido.

A cláusula “WHERE” é opcional. Se esta cláusula não for fornecida, o valor da coluna mencionada em toda a tabela será atualizado.

Eliminação de dados

A eliminação de dados significa excluir um registro completo da tabela do banco de dados. O comando ‘DELETE’ é usado para este propósito.

SQL em PL / SQL

Sintaxe Explicação:

A sintaxe acima mostra o comando DELETE. A palavra-chave ‘FROM’ é opcional e com ou sem a cláusula ‘FROM’ o comando se comporta da mesma forma.

A cláusula “WHERE” é opcional. Se esta cláusula não for fornecida, a tabela inteira será excluída.

Projeção de dados / busca

A projeção / busca de dados significa para recuperar os dados necessários da tabela do banco de dados. Isso pode ser alcançado usando o comando ‘SELECIONAR’ com a cláusula ‘INTO’. O comando ‘SELECT’ vai buscar os valores do banco de dados e cláusula de ‘INTO’ irá atribuir esses valores para a variável local do bloco PL / SQL.

Abaixo estão os pontos que precisam ser considerados na indicação “SELECIONAR”.

A instrução “SELECT” deve retornar apenas um registro enquanto usa a cláusula ‘INTO’, uma vez que uma variável pode conter apenas um valor. Se o ‘SELECT’ instrução retorna mais de um valor de exceção ‘TOO_MANY_ROWS’ será gerado.

A instrução “SELECT” atribuirá o valor à variável na cláusula ‘INTO’, por isso precisa obter pelo menos um registro da tabela para preencher o valor. Se não obteve nenhum registro, então a exceção ‘NO_DATA_FOUND’ é gerada.

O número de colunas e seu tipo de dados na cláusula ‘SELECIONAR’ devem corresponder com o número de variáveis ​​e seus tipos de dados na cláusula ‘INTO’.

Os valores são obtidos e preenchidos na mesma ordem mencionada na declaração.

A cláusula “WHERE” é opcional que permite ter mais restrição nos registros que serão obtidos.

A instrução “SELECT” pode ser usada na condição ‘WHERE’ de outras instruções DML para definir os valores das condições.

A instrução ‘SELECT’ ao usar as instruções ‘INSERT’, ‘UPDATE’, ‘DELETE’ não deve ter a cláusula ‘INTO’, uma vez que não irá preencher nenhuma variável nesses casos.

SQL em PL / SQL

Sintaxe Explicação:

A sintaxe acima mostra o comando SELECT-INTO. A palavra-chave ‘FROM’ é obrigatória que identifica o nome da tabela a partir do qual os dados precisam ser obtidos.

A cláusula “WHERE” é opcional. Se esta cláusula não for fornecida, os dados de toda a tabela serão obtidos.

Exemplo 1 : neste exemplo, vamos ver como executar operações DML em PL / SQL. Vamos inserir os seguintes 4 registros na tabela emp.

EMP_NAME EMP_NO SALÁRIO GERENTE
BBB 1000 25000 AAA
XXX 1001 10000 BBB
AAAA 1002 10000 BBB
ZZZ 1003 7500 BBB

Então, vamos atualizar o salário de ‘XXX’ para 15000, e vamos excluir o registro do funcionário ‘ZZZ’. Finalmente, vamos projetar os detalhes do “XXX” do empregado.

SQL em PL / SQL

SQL em PL / SQL

Explicação do código:

Código linha 2-5 : Declarando a variável.

Código linha 7-14 : Inserindo os registros na tabela emp.

Código linha 15 : Cometer as transações inserir.

Código linha 17-19 : atualizando o salário do empregado ‘XXX’ para 15000

Código linha 20 : Cometer a transação de atualização.

Código linha 22 : Excluindo o registro de ‘ZZZ’

Código linha 23 : Cometer a transação de exclusão.

  • Linha de código 25-27 : Selecionando a gravação de ‘XXX’ e preenchendo na variável l_emp_name, l_emp_no, l_salary, l_manager.

 

Linha de código 28-32 : exibindo o valor de registros obtidos.

CURSOR Concept em PL / SQL

O Oracle cria uma área de memória, conhecida como área de contexto, para processar uma instrução SQL, que contém todas as informações sobre a declaração, por exemplo, número de linhas processadas, etc. O cursor não é senão um ponteiro para essa área de contexto.

O PL / SQL permite ao programador controlar a área de contexto através do cursor. Um cursor contém as linhas retornadas pela instrução SQL. O conjunto de linhas que o cursor mantém é referido como conjunto ativo. Esses cursores também podem ser nomeados para que possam ser encaminhados a partir de outro local do código.

O cursor é de dois tipos.

Cursor implícito

Cursor explícito

Cursor implícito

Sempre que ocorrem operações DML no banco de dados, é criado um cursor implícito que contém as linhas afetadas, naquela operação específica. Esses cursores não podem ser nomeados e, portanto, não podem ser controlados ou encaminhados a partir de outro local do código. Podemos referir-se apenas ao cursor mais recente através dos atributos do cursor.

Cursor explícito

Os programadores podem criar área de contexto nomeada para executar suas operações DML para obter mais controle sobre isso. O cursor explícito deve ser definido na seção de declaração do bloco PL / SQL e é criado para a instrução ‘SELECT’ que precisa ser usada no código.

Abaixo estão as etapas que envolvem o trabalho com cursores explícitos.

Declarando o cursorDeclarar o cursor significa simplesmente criar uma área de contexto nomeada para a instrução ‘SELECIONAR’ que está definida na parte da declaração. O nome dessa área de contexto é o mesmo que o nome do cursor.

Cursor de aberturaAbrir o cursor instruirá o PL / SQL a alocar a memória para este cursor. Ele irá preparar o cursor para buscar os registros.

Obtendo Dados do CursorNeste processo, a instrução ‘SELECT’ é executada e as linhas obtidas são armazenadas na memória alocada. Estes são agora chamados de conjuntos ativos. Obter dados do cursor é uma atividade de nível recorde, o que significa que podemos acessar os dados de maneira recorde por gravação.Cada instrução fetch buscará um conjunto ativo e contém as informações desse registro específico. Esta declaração é a mesma que a instrução “SELECIONAR” que obtém a gravação e atribua à variável na cláusula ‘INTO’, mas não lançará nenhuma exceção.

Fechar o cursorUma vez que todos os registros são buscados, precisamos fechar o cursor para que a memória alocada para essa área de contexto seja lançada.

SQL em PL / SQL

Sintaxe Explicação:

  • Na sintaxe acima, a parte de declaração contém a declaração do cursor e a variável de cursor na qual os dados obtidos serão atribuídos.
  • O cursor é criado para a instrução ‘SELECT’ que é dada na declaração do cursor.
  • Na parte de execução, o cursor declarado é aberto, recuperado e fechado.

Atributos do cursor

Tanto o cursor implícito como o cursor explícito possuem certos atributos que podem ser acessados. Esses atributos fornecem mais informações sobre as operações do cursor. Abaixo estão os diferentes atributos do cursor e seu uso.

Atributo do Cursor Descrição
%ENCONTRADO Retorna o resultado booleano ‘VERDADEIRO’ se a operação de busca mais recente forçou uma gravação com sucesso, caso contrário, ela retornará FALSA
%NÃO ENCONTRADO Isso funciona da maneira oposta ao% FOUND retornará ‘TRUE’ se a operação de busca mais recente não puder obter qualquer registro.
%ESTÁ ABERTO Retorna o resultado booleano ‘TRUE’ se o cursor já estiver aberto, caso contrário ele retorna ‘FALSE’
%CONTAGEM DE LINHAS Ele retorna o valor numérico. Ele fornece a contagem real de registros que foram afetados pela atividade DML.

Exemplo 1 : neste exemplo, vamos ver como declarar, abrir, buscar e fechar o cursor explícito.

Vamos projetar todos os funcionários nome da tabela emp usando um cursor. Nós também usaremos o atributo do cursor para definir o loop para buscar toda a gravação a partir do cursor.

SQL em PL / SQL

Explicação do código:

  • Código linha 2 : Declarando o cursor guru99_det para a instrução ‘SELECT emp_name FROM emp’.
  • Código linha 3 : Declaração variável lv_emp_name.
  • Código linha 5 : abrindo o cursor guru99_det.
  • Código linha 6: Configurando a instrução do loop básico para buscar todos os registros na tabela ‘emp’.
  • Código linha 7: Obtém os dados guru99_det e atribua o valor a lv_emp_name.
  • Código linha 9: Usando o atributo do cursor ‘% NOTFOUND’ para descobrir se toda a gravação no cursor é buscada. Se for obtido, ele retornará ‘VERDADEIRO’ e o controle sairá do loop, senão o controle continuará comprando os dados do cursor e imprimindo os dados.
  • Código linha 11: condição EXIT para a instrução loop.
  • Linha de código 12: Imprima o nome do funcionário buscado.
  • Linha de código 14: Usando o atributo de cursor ‘% ROWCOUNT’ para encontrar o número total de registros que foram afetados / recuperados no cursor.
  • Código linha 15: Depois de sair do loop, o cursor é fechado e a memória alocada está livre.

FOR Loop Cursor statement

A indicação “PARA LOOP” pode ser usada para trabalhar com cursores. Podemos dar o nome do cursor em vez do limite de intervalo na instrução FOR loop para que o loop funcione a partir da primeira gravação do cursor para a última gravação do cursor. A variável do cursor, a abertura do cursor, a busca e o fechamento do cursor serão realizadas de forma implícita pelo loop FOR.

SQL em PL / SQL

Sintaxe Explicação:

  • Na sintaxe acima, a parte de declaração contém a declaração do cursor.
  • O cursor é criado para a instrução ‘SELECT’ que é dada na declaração do cursor.
  • Na parte de execução, o cursor declarado é configurado no loop FOR e a variável de loop ‘I’ se comportará como variável de cursor neste caso.

Exemplo 1 : neste exemplo, vamos projetar todo o nome do empregado da tabela emp usando um cursor-FOR loop.

SQL em PL / SQL

Explicação do código:

  • Código linha 2 : Declarando o cursor guru99_det para a instrução ‘SELECT emp_name FROM emp’.
  • Linha de código 4 : Construindo o loop ‘FOR’ para o cursor com a variável de loop lv_emp_name.
  • Código linha 5: Imprimir o nome do funcionário em cada iteração do loop.
  • Código linha 8: Sair do loop

Nota: No cursor Cursor-FOR, os atributos do cursor não podem ser usados, pois a abertura, a busca eo fechamento do cursor são feitos de forma implícita pelo loop FOR.

BULK COLLECT em PL / SQL

O Oracle PL / SQL fornece a funcionalidade de buscar os registros em massa em vez de buscar um a um. Este BULK COLLECT pode ser usado na instrução ‘SELECT’ para preencher os registros em massa ou em busca do cursor em massa. Uma vez que BULK COLLECT obtém o registro em BULK, a cláusula INTO deve sempre conter uma variável de tipo de coleção. A principal vantagem de usar BULK COLLECT é aumentar o desempenho, reduzindo a interação entre o banco de dados eo mecanismo PL / SQL.

SQL em PL / SQL

Sintaxe Explicação:

  • Na sintaxe acima, BULK COLLECT é usado para coletar os dados da indicação ‘SELECT’ e ‘FETCH’.

Cláusula FORALL

O FORALL permite executar as operações DML em dados a granel. É semelhante ao da declaração FOR loop, exceto no FOR loop coisas acontecem no nível recorde, enquanto que no FORALL não existe um conceito LOOP. Em vez disso, todos os dados presentes no intervalo especificado são processados ​​ao mesmo tempo.

SQL em PL / SQL

Sintaxe Explicação:

  • Na sintaxe acima, a operação DML dada será executada para todos os dados que estão presentes entre um intervalo mais baixo e mais alto.

Cláusula de Limite

O conceito de coleta em massa carrega todos os dados na variável de coleta de destino como um volume, ou seja, todos os dados serão preenchidos na variável de coleta em uma única etapa. Mas isso não é aconselhável quando o registro total que precisa ser carregado é muito grande, porque quando o PL / SQL tenta carregar todos os dados, ele consome mais memória de sessão. Por isso, é sempre bom limitar o tamanho desta operação de coleta em massa.

No entanto, esse limite de tamanho pode ser facilmente alcançado através da introdução da condição ROWNUM na instrução ‘SELECT’, enquanto que no caso do cursor isso não é possível.

Para superar este Oracle forneceu uma cláusula ‘LIMIT’ que define o número de registros que precisam ser incluídos no volume.

SQL em PL / SQL

Sintaxe Explicação:

  • Na sintaxe acima, a instrução de busca do cursor usa a instrução BULK COLLECT juntamente com a cláusula LIMIT.

BULK COLLECT Atributos

Semelhante aos atributos do cursor BULK COLLECT tem% BULK_ROWCOUNT (n) que retorna o número de linhas afetadas na n ª declaração DML da instrução FORALL, ou seja, dará a contagem de registros afetados na declaração FORALL para cada valor da coleção variável. O termo ‘n’ indica a seqüência de valor na coleção, para a qual a contagem de linhas é necessária.

Exemplo 1 : neste exemplo, vamos projetar todo o nome do empregado da tabela emp usando BULK COLLECT e também aumentaremos o salário de todos os funcionários em 5000 usando o FORALL.

SQL em PL / SQL

Explicação do código:

  • Código linha 2 : Declarando o cursor guru99_det para a instrução ‘SELECT emp_name FROM emp’.
  • Código linha 3 : Declarando lv_emp_name_tbl como tipo de tabela do VARCHAR2 (50)
  • Código linha 4 : Declarando lv_emp_name como lv_emp_name_tbl tipo.
  • Código linha 6: abrindo o cursor.
  • Código linha 7: Preenchendo o cursor usando BULK COLLECT com o tamanho LIMIT como 5000 intl lv_emp_name variável.
  • Código da linha 8-11: Configurando FOR loop para imprimir toda a gravação na coleção lv_emp_name.
  • Código linha 12: Usando FORALL atualizando o salário de todo o empregado em 5000.
  • Linha de código 14: Comprometer a transação.

Declarações TCL em PL / SQL

O TCL significa declarações de controle de transações. Ele irá salvar as transações pendentes ou reverter a transação pendente. Essas declarações desempenham o papel vital porque, a menos que a transação seja salva, as alterações por meio de instruções DML não serão salvas no banco de dados. Abaixo estão as diferentes declarações TCL.

COMMIT Salva toda a transação pendente
ROLLBACK Descarte toda a transação pendente
SAVEPOINT Cria um ponto na transação até que o retorno pode ser feito mais tarde
ROLLBACK TO Descarte toda a transação pendente até o especificado <save point>

A transação será completa nos seguintes cenários.

  • Quando qualquer uma das declarações acima é emitida (exceto SAVEPOINT)
  • Quando as declarações DDL são emitidas. (DML são declarações de confirmação automática)
  • QUANDO as declarações DCL são emitidas. (DCL são declarações de confirmação automática)

Transação Autônoma

Em PL / SQL, todas as modificações feitas em dados serão denominadas como uma transação. Uma transação é considerada completa quando o save / descarte é aplicado a ele. Se não for salvo / descartar, a transação não será considerada como completa e as modificações feitas nos dados não serão tornadas permanentes no servidor.

Independentemente de uma série de modificações feitas durante uma sessão, PL / SQL tratará toda a modificação como uma única transação e salvar / descartar essa transação afeta todas as mudanças pendentes naquela sessão. A Transação Autônoma fornece uma funcionalidade para o desenvolvedor em que permite fazer alterações em uma transação separada e salvar / descartar essa transação específica sem afetar a transação da sessão principal.

  • Essa transação autônoma pode ser especificada no nível do subprograma.
  • Para fazer qualquer subprograma para funcionar em uma transação diferente, a palavra-chave ‘PRAGMA AUTONOMOUS_TRANSATION’ deve ser fornecida na seção declarativa desse bloco.
  • Ele instruirá esse compilador a tratar isso como a transação separada e salvar / descartar dentro deste bloco não refletirá na transação principal.
  • Emitir COMMIT ou ROLLBACK é obrigatório antes de sair desta transação autônoma para a transação principal porque, em qualquer momento, apenas uma transação pode estar ativa.
  • Então, uma vez que fizemos uma transação autônoma, precisamos salvá-la e concluir a transação, então só podemos voltar para a transação principal.

SQL em PL / SQL

Sintaxe Explicação:

  • Na sintaxe acima, o bloco foi feito como uma transação autônoma.

Exemplo 1 : neste exemplo, vamos entender como a transação autônoma está funcionando.

SQL em PL / SQL

SQL em PL / SQL

Explicação do código:

  • Código linha 2 : declarando l_salary como NUMBER.
  • Código linha 3 : declarando procedimento de bloqueio aninhado
  • Código linha 4 : Fazendo o procedimento nested_block como ‘AUTONOMOUS_TRANSACTION’.
  • Código linha 7-9: aumentando o salário para o empregado número 1002 em 15000.
  • Código linha 10: Comprometer a transação.
  • Código linha 13-16: Imprimir os detalhes salariais dos funcionários 1001 e 1002 antes das alterações.
  • Código linha 17-19: aumentando o salário para o empregado número 1001 em 5000.
  • Código linha 20: Chamando o procedimento aninhado_block;
  • Código linha 21: descartar a transação principal.
  • Código linha 22-25: Imprimindo os detalhes do salário dos empregados 1001 e 1002 após as mudanças.
  • O aumento de salário para o empregado número 1001 não é refletido porque a principal transação foi descartada. O aumento de salário para o empregado número 1002 é refletido porque esse bloco foi feito como uma transação separada e salvo no final.
  • Portanto, independentemente da gravação / descarte na transação principal, as alterações na transação autônoma foram salvas sem afetar as principais alterações de transação.

Resumo

Neste tutorial, aprendemos a combinar o SQL em PL / SQL para manipulação de dados, Cursor Concepts, Cursor-FOR loop e Bulk collect usages. Nós também discutimos as declarações da TCL e como salvar / descartar transações separadamente.

Fonte

https://www.guru99.com/sql-pl-sql.html

Transaction Autonomous – O Que, Quando, Onde e Por Que

Do que se trata o artigo:

Neste artigo será apresentada a utilização do pragma autonomous Transaction para escrita de códigos autônomos em rotinas PL/SQL, as quais são executadas e commitadas na base independentemente do resultado da transação master que invocou essa rotina.


Em que situação o tema é útil:

Esta funcionalidade é bastante utilizada para geração de logs de erro de transação, onde a transação master sofre rollback depois de uma falha, mas é possível gerar um log contento os dados da transação que resultaram no erro.

Um subprograma normalmente tem suas operações salvas ou não no banco de dados de acordo com o que acontece com o programa principal onde ele está inserido. Isso quer dizer que, se uma procedure chama uma função e a procedure falha, nem as alterações feitas pela procedure nem as alterações feitas pela função são salvas na base, afinal trata-se da mesma transação, a qual é atômica (indivisível, ou seja, ou ela toda é commitada ou ela toda sofre rollback). No entanto, se a função contiver o pragma autonomous_transaction, ela se comporta como uma segunda transação, que é isolada e independente, e suas alterações na base podem ser salvas ou não independentemente da transação master que a originou.

A diretiva AUTONOMOUS_TRANSACTION altera a forma com que a transação trata a um subprograma. Um pragma na verdade é uma diretiva de compilação e os subprogramas marcados com este pragma são processados em tempo de compilação e não em tempo de execução, e passam informações diretamente ao compilador.

O termo AUTONOMOUS_TRANSACTION se refere à habilidade do PL/SQL temporariamente suspender a transação corrente e iniciar uma nova transação, totalmente independente, que funciona de forma autônoma com relação à transação original.

Imagine a seguinte situação: Para fins de auditoria, criamos uma tabela de log que contém os dados referentes a todas as alterações feitas nos dados de 5 tabelas críticas do banco de dados da empresa, armazenando o IP da máquina que originou a transação, qual tabela sofreu alteração, o que foi feito, etc, e um trigger é responsável por inserir tais dados nessa tabela. Pois bem, vamos supor então que por um motivo ou outro essa transação tenha falhado. Não desejamos que os logs de auditoria também sofram rollback, pois estaremos perdendo dados preciosos de tentativas frustradas de acesso não autorizado.

Neste caso, o trigger deve disparar um subprograma autônomo, cujo sucesso da transação não dependa do resultado da transação principal que o originou.

A utilização em tratativas de logs de auditoria são comuns e não causam nenhum tipo de problema ao banco de dados, uma vez que não está lidando com tabelas de negócio, ou seja, que guardam dados essenciais para o negócio. Por este motivo a transação autônoma é segura, pois a integridade do banco de dados está resguardada.

Digo isso porque já vi muitos códigos resolvendo regras de negócio com transações autônomas, o que pode gerar um problema grande para o banco de dados. Imagine que a alteração de um valor em uma tabela deve causar alterações em outras tabelas. Se a primeira alteração falha, o ideal é que as demais alterações não ocorram… neste caso o procedimento que faria as demais alterações não poderia jamais ser autônomo!

Qualquer subprograma, como procedures, funções ou até mesmo blocos anônimos PL/SQL podem conter este pragma. No entanto, se for utilizado dentro de pacotes, o pragma deve ser declarado para as funções e procedures que fazem parte do pacote, e não para o pacote em si.

Exemplo de Utilização

Como um exemplo de utilização da transação autônoma, vamos assumir que precisamos gravar logs de erro em uma tabela do banco de dados. Precisamos fazer rollback da transação principal porque ela resultaria em um erro, mas não queremos perder o log do que aconteceu nessa transação. A tabela que conterá os logs de erro possui a seguinte estrutura:

CREATE TABLE tb_log_erros(

  codigo integer,

  msg varchar2(2000),

  data date,

  usuario varchar2(50),

  nm_mach varchar2(100),

  prog varchar2(100)

);

O procedimento que deve ser invocado para inserir o log do erro na tabela é:

CREATE OR REPLACE PROCEDURE grava_log_erros(

   log_codigo IN INTEGER,

   log_msg IN VARCHAR2) IS

PRAGMA AUTONOMOUS_TRANSACTION;

CURSOR cur_erro IS

SELECT machine, program

FROM v$session

WHERE audsid = USERENV(‘SESSIONID’);

PT = Parent Transaction;

CT = Child Autonomous Transaction;

rec cur_erro%ROWTYPE;

BEGIN

   —

   OPEN cur_erro;

   FETCH cur_erro INTO rec;

   CLOSE cur_erro;

   —

   INSERT INTO tb_log_erros values (

       log_codigo,

       log_msg,

       SYSDATE,

       USER,

       rec.machine,

       rec.program

   );

   COMMIT;

EXCEPTION

   WHEN OTHERS THEN

       ROLLBAACK;

END;

/

Para testar o código acima, podemos executar o seguinte bloco anônimo PL/SQL:

BEGIN

    INSERT INTO HR.EMPLOYEES (first_name) VALUES (‘Maria’);

    COMMIT;

EXCEPTION

    WHEN OTHERS THEN

         grava_log_erros(SQLCODE,SQLERRM);

    ROLLBACK;

    RAISE;

END;

Ao executar o código acima, basta verificar nas tabelas EMPLOYEES e TB_LOG_ERROS as linhas inseridas, como segue:

SQL> select * from employees where first_name = ‘Maria’;

no rows selected.

SQL> select codigo, msg from tb_log_erros;

CODIGOMSG

——————————————————————————————————–

-1400ORA-01400: cannot insert NULL into (“HR”.”EMPLOYEES”.”EMPLOYEE_ID”)

Referências

BURLESON CONSULTING. PL/SQL Autonomous Transaction Tips. Burleson Consulting, 2015. Disponivel em: http://www.dba-oracle.com/t_autonomous_transaction.htm

ORACLE HELP CENTER. Autonomous_transaction Pragma. Database PL/SQL User’s Guide and Reference, 2017. Disponivel em: https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/autonotransaction_pragma.htm

Gatilhos escritos em PL/pgSQL

A linguagem PL/pgSQL pode ser utilizada para definir procedimentos de gatilho. O procedimento de gatilho é criado pelo comando CREATE FUNCTION, declarando o procedimento como uma função sem argumentos e que retorna o tipo trigger. Deve ser observado que a função deve ser declarada sem argumentos, mesmo que espere receber os argumentos especificados no comando CREATE TRIGGER — os argumentos do gatilho são passados através de TG_ARGV, conforme descrito abaixo.

Quando uma função escrita em PL/pgSQL é chamada como um gatilho, diversas variáveis especiais são criadas automaticamente no bloco de nível mais alto. São estas:

NEW
Tipo de dado RECORD; variável contendo a nova linha do banco de dados, para as operações de INSERT/UPDATE nos gatilhos no nível de linha. O valor desta variável é NULL nos gatilhos no nível de instrução.
OLD
Tipo de dado RECORD; variável contendo a antiga linha do banco de dados, para as operações de UPDATE/DELETE nos gatilhos no nível de linha. O valor desta variável é NULL nos gatilhos no nível de instrução.
TG_NAME
Tipo de dado name; variável contendo o nome do gatilho disparado.
TG_WHEN
Tipo de dado text; uma cadeia de caracteres contendo BEFORE ou AFTER, dependendo da definição do gatilho.
TG_LEVEL
Tipo de dado text; uma cadeia de caracteres contendo ROW ou STATEMENT, dependendo da definição do gatilho.
TG_OP
Tipo de dado text; uma cadeia de caracteres contendo INSERT, UPDATE, ou DELETE, informando para qual operação o gatilho foi disparado.
TG_RELID
Tipo de dado oid; o ID de objeto da tabela que causou o disparo do gatilho.
TG_RELNAME
Tipo de dado name; o nome da tabela que causou o disparo do gatilho.
TG_NARGS
Tipo de dado integer; o número de argumentos fornecidos ao procedimento de gatilho na instrução CREATE TRIGGER.
TG_ARGV[]
Tipo de dado matriz de text; os argumentos da instrução CREATE TRIGGER. O contador do índice começa por 0. Índices inválidos (menor que 0 ou maior ou igual a tg_nargs) resultam em um valor nulo.

Uma função de gatilho deve retornar nulo, ou um valor registro/linha possuindo a mesma estrutura da tabela para a qual o gatilho foi disparado.

Os gatilhos no nível de linha disparados BEFORE (antes) podem retornar nulo, para sinalizar ao gerenciador do gatilho para pular o restante da operação para esta linha (ou seja, os gatilhos posteriores não serão disparados, e não ocorrerá o INSERT/UPDATE/DELETE para esta linha. Se for retornado um valor diferente de nulo, então a operação prossegue com este valor de linha. Retornar um valor de linha diferente do valor original de NEW altera a linha que será inserida ou atualizada (mas não tem efeito direto no caso do DELETE). Para alterar a linha a ser armazenada, é possível substituir valores individuais diretamente em NEW e retornar o NEW modificado, ou construir um novo registro/linha completo a ser retornado.

O valor retornado por um gatilho BEFORE ou AFTER no nível de instrução, ou por um gatilho AFTER no nível de linha, é sempre ignorado; pode muito bem ser nulo. Entretanto, qualquer um destes tipos de gatilho pode interromper toda a operação gerando um erro.

O Exemplo 35-1 mostra um exemplo de procedimento de gatilho escrito em PL/pgSQL.

Exemplo 35-1. Procedimento de gatilho PL/pgSQL

O gatilho deste exemplo garante que quando é inserida ou atualizada uma linha na tabela, fica sempre registrado nesta linha o usuário que efetuou a inserção ou a atualização, e quando isto ocorreu. Além disso, o gatilho verifica se é fornecido o nome do empregado, e se o valor do salário é um número positivo.

CREATE TABLE emp (
    nome_emp       text,
    salario        integer,
    ultima_data    timestamp,
    ultimo_usuario text
);

CREATE FUNCTION emp_gatilho() RETURNS trigger AS $emp_gatilho$
    BEGIN
        -- Verificar se foi fornecido o nome e o salário do empregado
        IF NEW.nome_emp IS NULL THEN
            RAISE EXCEPTION 'O nome do empregado não pode ser nulo';
        END IF;
        IF NEW.salario IS NULL THEN
            RAISE EXCEPTION '% não pode ter um salário nulo', NEW.nome_emp;
        END IF;

        -- Quem paga para trabalhar?
        IF NEW.salario < 0 THEN
            RAISE EXCEPTION '% não pode ter um salário negativo', NEW.nome_emp;
        END IF;

        -- Registrar quem alterou a folha de pagamento e quando
        NEW.ultima_data := 'now';
        NEW.ultimo_usuario := current_user;
        RETURN NEW;
    END;
$emp_gatilho$ LANGUAGE plpgsql;

CREATE TRIGGER emp_gatilho BEFORE INSERT OR UPDATE ON emp
    FOR EACH ROW EXECUTE PROCEDURE emp_gatilho();

INSERT INTO emp (nome_emp, salario) VALUES ('João',1000);
INSERT INTO emp (nome_emp, salario) VALUES ('José',1500);
INSERT INTO emp (nome_emp, salario) VALUES ('Maria',2500);

SELECT * FROM emp;

 nome_emp | salario |        ultima_data         | ultimo_usuario
----------+---------+----------------------------+----------------
 João     |    1000 | 2005-11-25 07:07:50.59532  | folha
 José     |    1500 | 2005-11-25 07:07:50.691905 | folha
 Maria    |    2500 | 2005-11-25 07:07:50.694995 | folha
(3 linhas)

Exemplo 35-2. Procedimento de gatilho PL/pgSQL para registrar inserção e atualização

O gatilho deste exemplo garante que quando é inserida ou atualizada uma linha na tabela, fica sempre registrado nesta linha o usuário que efetuou a inserção ou a atualização, e quando isto ocorreu. Porém, diferentemente do gatilho anterior, a criação e a atualização da linha são registradas em colunas diferentes. Além disso, o gatilho verifica se é fornecido o nome do empregado, e se o valor do salário é um número positivo. [1]

CREATE TABLE emp (
    nome_emp       text,
    salario        integer,
    usu_cria       text,        -- Usuário que criou a linha
    data_cria      timestamp,   -- Data da criação da linha
    usu_atu        text,        -- Usuário que fez a atualização
    data_atu       timestamp    -- Data da atualização
);

CREATE FUNCTION emp_gatilho() RETURNS trigger AS $emp_gatilho$
    BEGIN
        -- Verificar se foi fornecido o nome do empregado
        IF NEW.nome_emp IS NULL THEN
            RAISE EXCEPTION 'O nome do empregado não pode ser nulo';
        END IF;
        IF NEW.salario IS NULL THEN
            RAISE EXCEPTION '% não pode ter um salário nulo', NEW.nome_emp;
        END IF;

        -- Quem paga para trabalhar?
        IF NEW.salario < 0 THEN
            RAISE EXCEPTION '% não pode ter um salário negativo', NEW.nome_emp;
        END IF;

        -- Registrar quem criou a linha e quando
        IF (TG_OP = 'INSERT') THEN
            NEW.data_cria := current_timestamp;
            NEW.usu_cria  := current_user;
        -- Registrar quem alterou a linha e quando
        ELSIF (TG_OP = 'UPDATE') THEN
            NEW.data_atu := current_timestamp;
            NEW.usu_atu  := current_user;
        END IF;
        RETURN NEW;
    END;
$emp_gatilho$ LANGUAGE plpgsql;

CREATE TRIGGER emp_gatilho BEFORE INSERT OR UPDATE ON emp
    FOR EACH ROW EXECUTE PROCEDURE emp_gatilho();

INSERT INTO emp (nome_emp, salario) VALUES ('João',1000);
INSERT INTO emp (nome_emp, salario) VALUES ('José',1500);
INSERT INTO emp (nome_emp, salario) VALUES ('Maria',250);
UPDATE emp SET salario = 2500 WHERE nome_emp = 'Maria';

SELECT * FROM emp;

 nome_emp | salario | usu_cria |         data_cria          | usu_atu |          data_atu
----------+---------+----------+----------------------------+---------+----------------------------
 João     |    1000 | folha    | 2005-11-25 08:11:40.63868  |         |
 José     |    1500 | folha    | 2005-11-25 08:11:40.674356 |         |
 Maria    |    2500 | folha    | 2005-11-25 08:11:40.679592 | folha   | 2005-11-25 08:11:40.682394
(3 linhas)

Uma outra maneira de registrar as modificações na tabela envolve a criação de uma nova tabela contendo uma linha para cada inserção, atualização ou exclusão que ocorra. Esta abordagem pode ser considerada como uma auditoria das mudanças na tabela. O Exemplo 35-3 mostra um procedimento de gatilho de auditoria em PL/pgSQL.

Exemplo 35-3. Procedimento de gatilho PL/pgSQL para auditoria

Este gatilho garante que todas as inserções, atualizações e exclusões de linha na tabela emp são registradas na tabela emp_audit, para permitir auditar as operações efetuadas na tabela emp. O nome de usuário e a hora corrente são gravadas na linha, junto com o tipo de operação que foi realizada.

CREATE TABLE emp (
    nome_emp    text NOT NULL,
    salario     integer
);

CREATE TABLE emp_audit(
    operacao    char(1)   NOT NULL,
    usuario     text      NOT NULL,
    data        timestamp NOT NULL,
    nome_emp    text      NOT NULL,
    salario     integer
);

CREATE OR REPLACE FUNCTION processa_emp_audit() RETURNS TRIGGER AS $emp_audit$
    BEGIN
        --
        -- Cria uma linha na tabela emp_audit para refletir a operação
        -- realizada na tabela emp. Utiliza a variável especial TG_OP
        -- para descobrir a operação sendo realizada.
        --
        IF (TG_OP = 'DELETE') THEN
            INSERT INTO emp_audit SELECT 'E', user, now(), OLD.*;
            RETURN OLD;
        ELSIF (TG_OP = 'UPDATE') THEN
            INSERT INTO emp_audit SELECT 'A', user, now(), NEW.*;
            RETURN NEW;
        ELSIF (TG_OP = 'INSERT') THEN
            INSERT INTO emp_audit SELECT 'I', user, now(), NEW.*;
            RETURN NEW;
        END IF;
        RETURN NULL; -- o resultado é ignorado uma vez que este é um gatilho AFTER
    END;
$emp_audit$ language plpgsql;

CREATE TRIGGER emp_audit
AFTER INSERT OR UPDATE OR DELETE ON emp
    FOR EACH ROW EXECUTE PROCEDURE processa_emp_audit();

INSERT INTO emp (nome_emp, salario) VALUES ('João',1000);
INSERT INTO emp (nome_emp, salario) VALUES ('José',1500);
INSERT INTO emp (nome_emp, salario) VALUES ('Maria',250);
UPDATE emp SET salario = 2500 WHERE nome_emp = 'Maria';
DELETE FROM emp WHERE nome_emp = 'João';

SELECT * FROM emp;

 nome_emp | salario
----------+---------
 José     |    1500
 Maria    |    2500
(2 linhas)

SELECT * FROM emp_audit;

 operacao | usuario |            data            | nome_emp | salario
----------+---------+----------------------------+----------+---------
 I        | folha   | 2005-11-25 09:06:03.008735 | João     |    1000
 I        | folha   | 2005-11-25 09:06:03.014245 | José     |    1500
 I        | folha   | 2005-11-25 09:06:03.049443 | Maria    |     250
 A        | folha   | 2005-11-25 09:06:03.052972 | Maria    |    2500
 E        | folha   | 2005-11-25 09:06:03.056774 | João     |    1000
(5 linhas)

Exemplo 35-4. Procedimento de gatilho PL/pgSQL para auditoria no nível de coluna

Este gatilho registra todas as atualizações realizadas nas colunas nome_emp e salario da tabela emp na tabela emp_audit (isto é, as colunas são auditadas). O nome de usuário e a hora corrente são registrados junto com a chave da linha (id) e a informação atualizada. Não é permitido atualizar a chave da linha. Este exemplo difere do anterior pela auditoria ser no nível de coluna, e não no nível de linha. [2]

CREATE TABLE emp (
    id          serial  PRIMARY KEY,
    nome_emp    text    NOT NULL,
    salario     integer
);

CREATE TABLE emp_audit(
    usuario         text      NOT NULL,
    data            timestamp NOT NULL,
    id              integer   NOT NULL,
    coluna          text      NOT NULL,
    valor_antigo    text      NOT NULL,
    valor_novo      text      NOT NULL
);

CREATE OR REPLACE FUNCTION processa_emp_audit() RETURNS TRIGGER AS $emp_audit$
    BEGIN
        --
        -- Não permitir atualizar a chave primária
        --
        IF (NEW.id <> OLD.id) THEN
            RAISE EXCEPTION 'Não é permitido atualizar o campo ID';
        END IF;
        --
        -- Inserir linhas na tabela emp_audit para refletir as alterações
        -- realizada na tabela emp.
        --
        IF (NEW.nome_emp <> OLD.nome_emp) THEN
           INSERT INTO emp_audit SELECT current_user, current_timestamp,
                       NEW.id, 'nome_emp', OLD.nome_emp, NEW.nome_emp;
        END IF;
        IF (NEW.salario <> OLD.salario) THEN
           INSERT INTO emp_audit SELECT current_user, current_timestamp,
                       NEW.id, 'salario', OLD.salario, NEW.salario;
        END IF;
        RETURN NULL; -- o resultado é ignorado uma vez que este é um gatilho AFTER
    END;
$emp_audit$ language plpgsql;

CREATE TRIGGER emp_audit
AFTER UPDATE ON emp
    FOR EACH ROW EXECUTE PROCEDURE processa_emp_audit();

INSERT INTO emp (nome_emp, salario) VALUES ('João',1000);
INSERT INTO emp (nome_emp, salario) VALUES ('José',1500);
INSERT INTO emp (nome_emp, salario) VALUES ('Maria',2500);
UPDATE emp SET salario = 2500 WHERE id = 2;
UPDATE emp SET nome_emp = 'Maria Cecília' WHERE id = 3;
UPDATE emp SET id=100 WHERE id=1;
ERRO:  Não é permitido atualizar o campo ID

SELECT * FROM emp;

 id |   nome_emp    | salario
----+---------------+---------
  1 | João          |    1000
  2 | José          |    2500
  3 | Maria Cecília |    2500
(3 linhas)

SELECT * FROM emp_audit;

 usuario |            data            | id |  coluna  | valor_antigo |  valor_novo
---------+----------------------------+----+----------+--------------+---------------
 folha   | 2005-11-25 12:21:08.493268 |  2 | salario  | 1500         | 2500
 folha   | 2005-11-25 12:21:08.49822  |  3 | nome_emp | Maria        | Maria Cecília
(2 linhas)

Uma das utilizações de gatilho é para manter uma tabela contendo o sumário de outra tabela. O sumário produzido pode ser utilizado no lugar da tabela original em diversas consultas — geralmente com um tempo de execução bem menor. Esta técnica é muito utilizada em Armazém de Dados (Data Warehousing), onde as tabelas dos dados medidos ou observados (chamadas de tabelas fato) podem ser muito grandes. O Exemplo 35-5 mostra um procedimento de gatilho em PL/pgSQL para manter uma tabela de sumário de uma tabela fato em um armazém de dados.

Exemplo 35-5. Procedimento de gatilho PL/pgSQL para manter uma tabela sumário

O esquema que está detalhado a seguir é parcialmente baseado no exemplo Grocery Store do livro The Data Warehouse Toolkit de Ralph Kimball.

--
-- Main tables - time dimension and sales fact.
--
CREATE TABLE time_dimension (
    time_key                    integer NOT NULL,
    day_of_week                 integer NOT NULL,
    day_of_month                integer NOT NULL,
    month                       integer NOT NULL,
    quarter                     integer NOT NULL,
    year                        integer NOT NULL
);
CREATE UNIQUE INDEX time_dimension_key ON time_dimension(time_key);

CREATE TABLE sales_fact (
    time_key                    integer NOT NULL,
    product_key                 integer NOT NULL,
    store_key                   integer NOT NULL,
    amount_sold                 numeric(12,2) NOT NULL,
    units_sold                  integer NOT NULL,
    amount_cost                 numeric(12,2) NOT NULL
);
CREATE INDEX sales_fact_time ON sales_fact(time_key);

--
-- Summary table - sales by time.
--
CREATE TABLE sales_summary_bytime (
    time_key                    integer NOT NULL,
    amount_sold                 numeric(15,2) NOT NULL,
    units_sold                  numeric(12) NOT NULL,
    amount_cost                 numeric(15,2) NOT NULL
);
CREATE UNIQUE INDEX sales_summary_bytime_key ON sales_summary_bytime(time_key);

--
-- Function and trigger to amend summarized column(s) on UPDATE, INSERT, DELETE.
--
CREATE OR REPLACE FUNCTION maint_sales_summary_bytime() RETURNS TRIGGER AS $maint_sales_summary_bytime$
    DECLARE
        delta_time_key          integer;
        delta_amount_sold       numeric(15,2);
        delta_units_sold        numeric(12);
        delta_amount_cost       numeric(15,2);
    BEGIN

        -- Work out the increment/decrement amount(s).
        IF (TG_OP = 'DELETE') THEN

            delta_time_key = OLD.time_key;
            delta_amount_sold = -1 * OLD.amount_sold;
            delta_units_sold = -1 * OLD.units_sold;
            delta_amount_cost = -1 * OLD.amount_cost;

        ELSIF (TG_OP = 'UPDATE') THEN

            -- forbid updates that change the time_key -
            -- (probably not too onerous, as DELETE + INSERT is how most
            -- changes will be made).
            IF ( OLD.time_key != NEW.time_key) THEN
                RAISE EXCEPTION 'Update of time_key : % -> % not allowed', OLD.time_key, NEW.time_key;
            END IF;

            delta_time_key = OLD.time_key;
            delta_amount_sold = NEW.amount_sold - OLD.amount_sold;
            delta_units_sold = NEW.units_sold - OLD.units_sold;
            delta_amount_cost = NEW.amount_cost - OLD.amount_cost;

        ELSIF (TG_OP = 'INSERT') THEN

            delta_time_key = NEW.time_key;
            delta_amount_sold = NEW.amount_sold;
            delta_units_sold = NEW.units_sold;
            delta_amount_cost = NEW.amount_cost;

        END IF;


        -- Update the summary row with the new values.
        UPDATE sales_summary_bytime
            SET amount_sold = amount_sold + delta_amount_sold,
                units_sold = units_sold + delta_units_sold,
                amount_cost = amount_cost + delta_amount_cost
            WHERE time_key = delta_time_key;


        -- There might have been no row with this time_key (e.g new data!).
        IF (NOT FOUND) THEN
            BEGIN
                INSERT INTO sales_summary_bytime (
                            time_key,
                            amount_sold,
                            units_sold,
                            amount_cost)
                    VALUES (
                            delta_time_key,
                            delta_amount_sold,
                            delta_units_sold,
                            delta_amount_cost
                           );
            EXCEPTION
                --
                -- Catch race condition when two transactions are adding data
                -- for a new time_key.
                --
                WHEN UNIQUE_VIOLATION THEN
                    UPDATE sales_summary_bytime
                        SET amount_sold = amount_sold + delta_amount_sold,
                            units_sold = units_sold + delta_units_sold,
                            amount_cost = amount_cost + delta_amount_cost
                        WHERE time_key = delta_time_key;

            END;
        END IF;
        RETURN NULL;

    END;
$maint_sales_summary_bytime$ LANGUAGE plpgsql;

CREATE TRIGGER maint_sales_summary_bytime
AFTER INSERT OR UPDATE OR DELETE ON sales_fact
    FOR EACH ROW EXECUTE PROCEDURE maint_sales_summary_bytime();

Exemplo 35-6. Procedimento de gatilho para controlar sobreposição de datas

O gatilho deste exemplo verifica se o compromiso sendo agendado ou modificado se sobrepõe a outro compromisso já agendado. Se houver sobreposição, emite mensagem de erro e não permite a operação. [3]

Abaixo está mostrado o script utilizado para criar a tabela, a função de gatilho e os gatilhos de inserção e atualização.

CREATE TABLE agendamentos (
    id          SERIAL PRIMARY KEY,
    nome        TEXT,
    evento      TEXT,
    data_inicio TIMESTAMP,
    data_fim    TIMESTAMP
);

CREATE FUNCTION fun_verifica_agendamentos() RETURNS "trigger" AS
$fun_verifica_agendamentos$
    BEGIN
        /* Verificar se a data de início é maior que a data de fim */
        IF NEW.data_inicio > NEW.data_fim THEN
           RAISE EXCEPTION 'A data de início não pode ser maior que a data de fim';
        END IF;
        /* Verificar se há sobreposição com agendamentos existentes */
        IF EXISTS (
            SELECT 1
                FROM agendamentos
                WHERE nome = NEW.nome
                  AND ((data_inicio, data_fim) OVERLAPS
                       (NEW.data_inicio, NEW.data_fim))
        )
        THEN
            RAISE EXCEPTION 'impossível agendar - existe outro compromisso';
        END IF;
        RETURN NEW;
    END;
$fun_verifica_agendamentos$ LANGUAGE plpgsql;

COMMENT ON FUNCTION fun_verifica_agendamentos() IS
    'Verifica se o agendamento é possível';

CREATE TRIGGER trg_agendamentos_ins
    BEFORE INSERT ON agendamentos
    FOR EACH ROW
    EXECUTE PROCEDURE fun_verifica_agendamentos();

CREATE TRIGGER trg_agendamentos_upd
    BEFORE UPDATE ON agendamentos
    FOR EACH ROW
    EXECUTE PROCEDURE fun_verifica_agendamentos();

Abaixo está mostrado um exemplo de utilização do gatilho. Deve ser observado que os intervalos (‘2005-08-23 14:00:00’, ‘2005-08-23 15:00:00’) e (‘2005-08-23 15:00:00’, ‘2005-08-23 16:00:00’) não se sobrepõem, uma vez que o primeiro intervalo termina às quinze horas, enquanto o segundo intervalo inicia às quinze horas, estando, portanto, o segundo intervalo imediatamente após o primeiro.

=> INSERT INTO agendamentos VALUES (DEFAULT,'Joana','Congresso','2005-08-23','2005-08-24');
=> INSERT INTO agendamentos VALUES (DEFAULT,'Joana','Viagem','2005-08-24','2005-08-26');
=> INSERT INTO agendamentos VALUES (DEFAULT,'Joana','Palestra','2005-08-23','2005-08-26');
ERRO:  impossível agendar - existe outro compromisso
=> INSERT INTO agendamentos VALUES (DEFAULT,'Maria','Cabeleireiro','2005-08-23 14:00:00','2005-08-23 15:00:00');
=> INSERT INTO agendamentos VALUES (DEFAULT,'Maria','Manicure','2005-08-23 15:00:00','2005-08-23 16:00:00');
=> INSERT INTO agendamentos VALUES (DEFAULT,'Maria','Médico','2005-08-23 14:30:00','2005-08-23 15:00:00');
ERRO:  impossível agendar - existe outro compromisso
=> UPDATE agendamentos SET data_inicio='2005-08-24' WHERE id=2;
ERRO:  impossível agendar - existe outro compromisso
=> SELECT * FROM agendamentos;

 id | nome  |    evento    |     data_inicio     |      data_fim
----+-------+--------------+---------------------+---------------------
  1 | Joana | Congresso    | 2005-08-23 00:00:00 | 2005-08-24 00:00:00
  2 | Joana | Viagem       | 2005-08-24 00:00:00 | 2005-08-26 00:00:00
  4 | Maria | Cabeleireiro | 2005-08-23 14:00:00 | 2005-08-23 15:00:00
  5 | Maria | Manicure     | 2005-08-23 15:00:00 | 2005-08-23 16:00:00
(4 linhas)

Notas

[1] Exemplo escrito pelo tradutor, não fazendo parte do manual original.
[2] Exemplo escrito pelo tradutor, não fazendo parte do manual original.
[3] Exemplo escrito pelo tradutor, não fazendo parte do manual original, baseado em exemplo da lista de discussão pgsql-sql.

 

Fonte: http://pgdocptbr.sourceforge.net/pg80/plpgsql-trigger.html#PLPGSQL-TRIGGER-EXAMPLE1

Sistemas de Banco de Dados 6ª Edição – Elmasri

 

sistemas-de-banco-de-dados-6

Download Sistemas de Banco de Dados 6ª Edição Elmasris

Referência acadêmica tanto teórica como prática, Sistemas de banco de dados apresenta os aspectos mais importantes não apenas dos sistemas, mas também das aplicações de banco de dados, além de diversas tecnologias relacionadas ao assunto.

Atualizada, a obra aborda:
– Conceitos fundamentais para projetar e usar os sistemas de banco de dados.
– Fundamentos de modelagem e de projeto de banco de dados.
– Linguagens e modelos fornecidos pelos sistemas de gerenciamento de banco de dados.
– Técnicas de implementação do sistema de banco de dados, com exemplos práticos.
Indicado para os cursos de ciências da computação, desenvolvimento de sistemas, sistemas de informação e engenharia da computação, este livro é também bibliografia básica para cursos de análise de redes, análise de sistemas e processamento de dados.

Sumário
Parte 1. Introdução aos bancos de dados.
1. Bancos de dados e usuários de banco de dados.
2. Conceitos e arquitetura do sistema de banco de dados.

Parte 2. Modelo de dados relacional e SQL.
3. O modelo de dados relacional e as restrições em bancos de dados relacionais.
4. SQL básica.
5. Mais SQL: Consultas complexas, triggers, views e modificação de esquema.
6. Álgebra e cálculo relacional.

Parte 3. Modelagem conceitual e projeto de banco de dados.
7. Modelagem de dados usando o modelo de Entidade-Relacionamento (ER).
8. O modelo de entidade-relacionamento estendido (EER).
9. Projeto de banco de dados relacional por mapeamento de ER e EER para relacional.
10. Metodologia prática de projeto de banco de dados e uso de diagramas UML.

Parte 4. Objeto, objeto-relacional e XML: conceitos, modelos, linguagens e padrões.
11. Bancos de dados de objeto e objeto-relacional.
12. XML: Extensible Markup Language.

Parte 5. Técnicas de programação de banco de dados.
13. Introdução às técnicas de programação SQL.
14. Programação de banco de dados Web usando PHP.

Parte 6. Teoria e normalização de projeto de banco de dados.
15. Fundamentos de dependências funcionais e normalização para bancos de dados relacionais.
16. Algoritmos de projeto de banco de dados relacional e demais dependências.

Parte 7. Estruturas de arquivo, indexação e hashing.
17. Armazenamento de disco, estruturas de arquivo básicas e hashing.
18. Estruturas de indexação para arquivos.

Parte 8. Processamento de consulta, otimização e ajuste de banco de dados; 19. Algoritmos para processamento e otimização de consulta.
20. Projeto físico e ajuste de banco de dados.

Parte 9. Processamento de transações, controle de concorrência e recuperação; 21. Introdução aos conceitos e teoria de processamento de transações.
22. Técnicas de controle de concorrência.
23. Técnicas de recuperação de banco de dados.

Parte 10. Tópicos adicionais de banco de dados: segurança e distribuição
24.Segurança de banco de dados
25. Bancos de dados distribuídos.

Parte 11. Modelos, sistemas e aplicações de bancos de dados avançados.
26. Modelos de dados avançados para aplicações avançadas.
27. Introdução à recuperação de informações e busca na Web.
28. Conceitos de data mining.
29. Visão geral de data warehousing e OLAP; Apêndices; Bibliografia; Índice remissivo.

Estilo: Curso
Tamanho: 131 mb
Ano de Lançamento: 2011
Idioma: Português – BR
Formato: Rar / Pdf
Hospedagem: Depositfiles / Freakshare / Bitshare

Depositfiles Download
Freakshare Download

Freakshare Bitshare

 

Fonte: http://www.sempredownloadfull.net/sistemas-de-banco-de-dados-6-edico-elmasri.html

Mais de 600GB de material para estudo em TI: Cursos, vídeo aulas, livros, apostilas de todas as variantes da Tecnologia da informação:

 60 GB em vídeos aulas de Java 16 DVDS – Senha = pr0mp7.torrent

Tamanho:153 KB
https://mega.co.nz/#!JRgjRLBT!nNg8JO31WWskPXH96xn1efu9mZqfgM%20jVZo24v6CAiLg

Livro Python para Pentester e Hackers

https://mega.nz/#!atQHACib!jff1wMGqCDMq1s8CjGWcbLDAcgol53DXvWYrwehV6tE

Curso de PHP

https://mega.nz/#F!WJVmQI4K!oosRA55mOWFMGR5qu9ssJg

Curso DreamWeaver

https://mega.nz/#F!AUhkiSpK!HlSxR0lexLecXjCowGG3AQ

Curso de Redes

https://mega.co.nz/#F!hZxDHLIZ!Pw8xfRmJirbL9Jvvip_iKw

Segurança em Redes

https://mega.co.nz/#F!cdQWjA5S!cX1sn4-sDpl1iWTH2b8-8w

Banco de Dados

https://mega.co.nz/#F!4R4ywJYb!-QLSTcDQ7GyhLeauC9HOlA

Curso de Eletrônica

https://mega.co.nz/#F!EYplFZRJ!Hd3g53t4SWuZ_ocF1fGLaw

Curso de JOOMLA completo

https://mega.co.nz/#F!kAohEChQ!C0XDspJDpw7tVxAgZizcaw

Curso de Linux

https://mega.co.nz/#F!YNI3kS5R!VsbYhu0sYIidqlKwwnH14Q

Curso Hardware

https://mega.co.nz/#F!EBAUCBDC!M2L3z07ypj05HtAQSeXkGA

Mega pacote de cursos Alura

https://mega.nz/#!FhxXwK7K!-Kzt-IDBs-rhVWC1_DgaULd7vSkZG7dWULCi_99kiOY

Curso Wireless Hacking

https://mega.co.nz/#F!AFJm2TLK!I6f4pZSX2ltoGBs0b1ztsQ

Curso WordPress

https://mega.co.nz/#F!cBIUBDTZ!Qtx1ahx-YeXUPdzIghwatA

Engenharia de software

https://mega.co.nz/#F!gUAmjbpD!BW7cylJHD_rcO1rryJ1sVQ

Hacking

https://mega.co.nz/#F!ER53kboI!H2RKhe5oMegv0APK2cQoFQ

https://mega.co.nz/#F!9QhWHbTI!oarMp7t3tzyY_yu08KHoEQ

Hardware

https://mega.co.nz/#F!oIZW3AzQ!LqcZV5fNLLmsxKfXAl6EtA

Introdução aos Sistemas Operacionais

https://mega.co.nz/#F!oZpVgbTR!MnX35yBQTexHPm4J8nIP2A

Linux

https://mega.co.nz/#F!YNg3xYhY!KQxsOV5rOF4ZhZm5LaiTwQ

Linux Essentials

https://mega.co.nz/#F!sBZhXDAI!NCWJslFznUXBaymdg_kmuA

Lógica de Programação Usando Python

https://mega.co.nz/#F!QAZ31aYY!JtCs0a5who41VK3jNsBa4Q

OYS pentest – Curso Teste de Invasão em Redes e Sistemas

https://mega.co.nz/#F!dVQkDTIQ!MLNKb5ZELHuIarpqHA0HxQ

Programação WEB

https://mega.co.nz/#F!AQQU3LYI!MIYAsxFZtfFTxpIqfHfIBg

Redes

https://mega.co.nz/#F!NMh1SZQC!5CKtEXGJy2JrIafPhvUuew

Segurança

https://mega.co.nz/#F!MN402QIb!_S4Jg-opFAFQVtl3lR4yJQ

Sistemas Operacionais

https://mega.co.nz/#F!JJAVwQAC!FB-jqhynRl_3CUuNzt7oMw

Software Livre

https://mega.co.nz/#F!EMgUkKxI!Wmv2SRC5bQNiLaZdbNBa9w

Teste de Invasão em Redes Sem Fio

https://mega.co.nz/#F!AUQwgIpa!NFW83TBeph3-7A7-LZqy4Q

Apostila HTML CSS

https://mega.co.nz/#!8FpXjbKB!11EMXK2wdfH3OC5BseR0PMbT9MYSGO%20tMtJrfiv5umEE

Artigo – wireshark

https://mega.co.nz/#!pc43VIpR!qy50wLU0yM7TsaeJtNu7RdaFw88BId%20VmDxCqd_E7ouQ

Curso Android Básico

https://mega.co.nz/#!pRAglZqB!hxJ9kG6dvUVukuT5tKQFMzf7_2jKdx%20V4SjM-IFzl2ns

Curso Banco de dados SQL e Modelagem

https://mega.co.nz/#!QYZSlCLB!FudRrApaiBV1oshkcHo2Rm38KeKSk1%20i_WN_0G84Q41M

Curso completo de Python

https://mega.co.nz/#!pEwA1IBL!REq1z_rnrc-ttqhEI-aGnxHcxc__0x%20gix5F98CwCkKI

Curso Linux

https://mega.co.nz/#!JIxVgYTZ!2aVR4SMtttlGoaEbTl7NGXa8n_VuhE%20K9XzjrlchSqss

Curso ipv6

https://mega.co.nz/#!xd50wAjA!sXt5m6tdZkZ_0ppNw7RKAw9gWgNYsM%20qVR12tr9FoTvM

Hackeando Mentes

https://mega.co.nz/#!kIBzmYAQ!VEYe_yI1Q6xBBsq_m5yvv_eIG3DH3n%20Xbp2AKkqLly88

Hacker inside

https://mega.co.nz/#!9ZgSyCCY!sBTV9Mva-fCYw5QKF0TkJfolcDsuox%20KqadjDqrjQTIM

Kevinmitnick a arte de enganar

https://mega.co.nz/#!INJglDRQ!H1KGBLTP9pEWtfZrp5VAbspu0Uo_Me%20_hkvtNh4B3Dm0

Banco de dados

https://mega.nz/#F!edRGmCIC!RS7TIjy7Krd4blcpLk2_hw

Computação Forense

https://mega.nz/#F!LVZgyKxT!0UEl9uphWKK5XN2iHo2ZTg

Curso inglês

https://mega.nz/#F!rMQW2CiD!nUNJvZ1nIeRHBMx33Vw8oQ

DeepWeb

https://mega.nz/#F!SdACSJSL!ck9c2S2FvjdI-L1ji-8JkQ

Edição de imagens

https://mega.nz/#F!vFIGFBpI!eRnEOpNziIS_mZx4IAIUsg

Engenharia de software

https://mega.nz/#F!ScwiGDhY!mFZz6mdkPMGVs5_6ZPOQeQ

Hacking

https://mega.nz/#F!vVoUhSrY!CCRwM3BC7U31BaAFZHl5SQ

Introdução a sistemas operacionais

https://mega.nz/#F!3doigIaC!pbDI81QC_3K2sD-Y08i1_g

Microsoft office

https://mega.nz/#F!KE4h2KQJ!ARugbDhPAqm9WWet6R606g

Normas para a apresentação de trabalhos acadêmicos

https://mega.nz/#F!2YpWWYrQ!njzFN2wdEjcL-n48ouCwvA

Programação WEB

https://mega.nz/#F!Lc4jwILR!YjIOrB8spSKjbwHmNvP8hQ

Redes

https://mega.nz/#F!vdIXgCRB!LpBx2GGbuthGu7FLHL5CsA

Segurança

https://mega.nz/#F!bFgHiBZB!XHC6bDoVYO3JEMJzf3pPmg

Sistemas operacionais

https://mega.nz/#F!fBxDULYK!g6jOZV3cjXwLYzuWhqCUnA

Software Livre

https://mega.nz/#F!HFABDDgQ!eH-cL2wdBu5y_fbY8yV78A

Teoria da computação

https://mega.nz/#F!rRwjTSiC!QOCkako5vL8sIarKYrZHPA

Vídeo aulas

https://mega.nz/#F!iJgkhDRI!LcvTfLA5rRUe1fwdqa1BUA

São tantos cursos que não dá nem pra mencionar aqui do que eles tratam, mas tem coisa muito boa lá, e grande parte deles são bem atuais, tratando sobre Web, Deepweb, Programação, Pentest, Hacker, Linux. Office, Idiomas, e muitos mais.

+BONUS DE MAIS 380GB em cursos ainda não catalogados:

https://mega.co.nz/#F!98cg2TSR!1q1OctEo3sOq25J11JAbOg

https://mega.nz/#F!V55BFDbD!3cBs3zMuk168LXfhfRmm-g
https://mega.nz/#F!wVsCjS7A!K7jrAMW6b7RX_AC6TT3msA!tZcAXCrK
https://mega.nz/#F!mIcTSRgJ!or6uaG2MJdh4jEKuHPYo_g!SAEDHBbB
https://mega.nz/#F!wVsCjS7A!K7jrAMW6b7RX_AC6TT3msA!ARcBlRhZ
https://mega.nz/#F!WJVmQI4K!oosRA55mOWFMGR5qu9ssJg
https://mega.nz/#F!wVsCjS7A!K7jrAMW6b7RX_AC6TT3msA
https://mega.nz/#F!WcBzgZhK!pJ1WsYkq8Evo1EhJi5oiJA
https://mega.nz/#F!mBB1BSrJ!RPojuKs757rJAIk-hVo4vw

https://mega.nz/#F!khhRAbwa!W5xZdG5Yat_y10Em_rmCng

https://mega.nz/#F!AE9GlDRT!mQQ1laUDxLw52-q1DljDsg

https://mega.nz/#F!CV9WFJYK!cjNuwXYg5wm6rc0YZTqaIg

https://mega.nz/#F!YF12iJ6B!933zM4O_EAxQWR16jC7I3Q

https://mega.nz/#F!ml8xGDYT!8LXsPyDMvQj8jWaM1k4rYQ

https://mega.nz/#F!tsNijbTR!Qj–39YrI4RsIwu6NTrfTQ

http://suporteninja.com/mais-de-300gb-de-cursos-em-ti-para-download-no-mega/

( Na verdade tem mais de 600GB de conteúdo)

Restaurando backup com pg_restore

Restaurando backup com pg_restore

pg_restore —  restaura um banco de dados do PostgreSQL a partir de um arquivo gerado pelo pg_dump

Synopsis

pg_restore [ -a ] [ -c ] [ -C ] [ -d nome_bd ] [ -f arquivo_de_saída ] [ -F formato ] [ -i índice ] [ -l ] [ -L arquivo_da_listagem ] [ -N | -o | -r ] [ -O ] [ -P nome_da_função ] [ -R ] [ -s ] [ -S ] [ -t tabela ] [ -T gatilho ] [ -v ] [ -x ] [ -X palavra_chave] [ -h hospedeiro ] [ -p porta ] [ -U nome_do_usuário ] [ -W ] [ arquivo_de_exportação ]

Descrição:

O pg_restore é um utilitário para restaurar um banco de dados do PostgreSQL a partir de um arquivo gerado pelo pg_dump em um dos formatos não-texto-puro. São executados os comandos necessários para criar novamente todos os tipos, funções, tabelas, índices, agregações e operadores definidos pelo usuário, assim como os dados das tabelas.

Os arquivos de exportação contêm informações para o pg_restore reconstruir o banco de dados, mas também permitem ao pg_restore selecionar o que deve ser restaurado, ou mesmo reordenar a restauraração dos itens. Os arquivos de exportação são projetados para serem portáveis entre arquiteturas.

O pg_restore pode operar de dois modos: Se um nome de banco de dados for especificado, o arquivo de exportação é restaurado diretamente no banco de dados. Senão, um script contendo os comandos SQL necessários para reconstruir o banco de dados é criado (e escrito em um arquivo ou na saída padrão), semelhante aos scripts criados pelo pg_dump no formato texto-puro. Algumas das opções que controlam a criação do script são, portanto, análogas às opções do pg_dump.

Obviamente, o pg_restore não pode restaurar informações que não estejam presentes no arquivo de exportação; por exemplo, se o arquivo de exportação foi gerado usando a opção “exportar dados como INSERT”, o pg_restore não poderá importar os dados usando o comando COPY.
Opções

O pg_restore aceita os seguintes argumentos de linha de comando (As formas longas das opções estão disponíveis em algumas plataformas apenas).

nome_do_arquivo_exportado
Especifica a localização do arquivo de exportação a ser restaurado. Se não for especificado, a entrada padrão é usada.

-a
–data-only

Importa somente os dados, não o esquema (definições dos dados).

-c
–clean

Exclui (drop) os objetos do banco de dados antes de criá-los..

-C
–create

Cria o banco de dados antes de restaurá-lo (Quando esta opção está presente, o banco de dados designado por -d é usado apenas para executar o comando CREATE DATABASE inicial. Todos os dados são restaurados no banco de dados cujo nome aparece no arquivo de exportação).

-d nome_bd
–dbname=nome_bd

Conecta ao nome_bd e restaura diretamente no banco de dados. Os objetos grandes somente podem ser restaurados usando uma conexão direta ao banco de dados.

-f arquivo_de_saída
–file=arquivo_de_saída

Especifica o nome do arquivo contendo o script gerado, ou a listagem quando for utilizado com a opção -l. Por padrão a saída padrão.

-F formato
–format=formato

Especifica o formato do arquivo de exportação. Não é necessário especificar o formato, porque o pg_restore reconhece o formato automaticamente. Se for especificado, poderá ser um dos seguintes:

t

O arquivo de exportação está no formato tar. Este formato de arquivo de exportação permite reordenar e/ou excluir elementos do esquema durante a importação. Também permite limitar quais dados são recarregados durante a importação.

c

O arquivo de exportação está no formato personalizado do pg_dump. Este é o formato mais flexível porque permite a reordenação da importação dos dados e dos elementos do esquema. Este formato também é comprimido por padrão.

-i índice
–index=índice

Restaura a definição do índice para o índice especificado apenas.

-l
–list

Lista o conteúdo do arquivo de exportação. A saída deste comando pode ser usada com a opção -L para restringir e reordenar os itens que são restaurados.

-L arquivo_da_listagem
–use-list=arquivo_da_listagem

Restaura apenas os elementos presentes no arquivo_da_listagem, e na ordem em que aparecem neste arquivo. As linhas podem ser movidas e, também, podem virar comentário colocando-se um ; no seu início.

-N
–orig-order

Restaura os itens na ordem original de exportação. Por padrão, o pg_dump irá exportar os itens em uma ordem conveniente para o pg_dump, e depois salvar o arquivo de exportação em uma ordem de OID modificada. Esta opção substitui a da ordem de OID.

-o
–oid-order

Restaura os itens na ordem de OID. Por padrão o pg_dump irá exportar exporta os itens em uma ordem conveniente para o pg_dump, e depois salvar o arquivo de exportação em uma ordem de OID modificada. Esta opção impõe a estrita ordem de OID.

-O
–no-owner

Impede qualquer tentativa de restaurar o dono original do objeto. O dono dos objetos será o usuário conectado ao banco de dados.

-P nome_da_função
–function=nome_da_função

Especifica o procedimento ou a função a ser restaurada.

-r
–rearrange

Restaura os itens na ordem modificada de OID. Por padrão, o pg_dump irá exportar os itens em uma ordem conveniente para o pg_dump, e depois salvar o arquivo de exportação em uma ordem de OID modificada. A maior parte dos objetos é restaurada na ordem de OID, mas alguns elementos (por exemplo, regras e índices) são restaurados no fim do processo sem respeitar os OIDs. Esta é a opção padrão.

-R
–no-reconnect

Durante a restauração do arquivo de exportação, o pg_restore usualmente necessita reconectar ao banco de dados vária vezes com nomes de usuário diferentes, para definir o dono correto dos objetos criados. Se isto não for desejável (por exemplo, se a intervenção manual for necessária para cada reconexão), esta opção proíbe o pg_restore requisitar reconexões (uma requisição de conexão em modo texto-puro, não conectado ao banco de dados, é feita emitindo o comando \connect do psql). Entretanto, esta opção é um instrumento bastante rudimentar, porque faz o pg_restore perder a informação sobre o dono, a menos que seja usada a opção -X use-set-session-authorization.

-s
–schema-only

Restaura somente o esquema (definições dos dados), sem os dados. Os valores das seqüências são substituídos.

-S nome_do_usuário
–superuser=nome_do_usuário

Especifica o nome do superusuário a ser usado para desativar os gatilhos e/ou definir o dono dos elementos do esquema. Por padrão, o pg_restore usa o nome do usuário corrente se este for um superusuário.

-t tabela
–table=tabela

Restaurar o esquema/dados da tabela apenas.

-T gatilho
–trigger=gatilho

Restaurar a definição do gatilho apenas.

-v
–verbose

Especifica o modo verboso.

-x
–no-privileges
–no-acl

Proíbe a restauração dos privilégios de acesso (comandos GRANT/REVOKE).

-X use-set-session-authorization
–use-set-session-authorization

Normalmente, se ao restaurar um arquivo de exportação for necessário trocar o usuário corrente do banco de dados (por exemplo, para definir o dono correto do objeto), uma nova conexão ao banco de dados deve ser aberta, o que poderá requerer intervenção manual (por exemplo, senhas). Se for usada a opção -X use-set-session-authorization, então o pg_restore vai usar o comando SET SESSION AUTHORIZATION. Embora produza o mesmo efeito, requer que o usuário que for fazer a importação do banco de dados a partir do arquivo de exportação gerado seja um superusuário. Esta opção substitui a opção -R.

O pg_restore também aceita os seguintes argumentos de linha de comando para os parâmetros de conexão:

-h hospedeiro
–host=hospedeiro

Especifica o nome da máquina onde o servidor está executando. Se o nome iniciar por uma barra (/), é considerado como sendo o diretório do soquete do domínio Unix.

-p porta
–port=porta

Especifica a porta Internet TCP/IP, ou o soquete do domínio local Unix, onde o servidor está aguardando as conexões. O padrão para o número da porta é 5432, ou o valor da variável de ambiente PGPORT (se estiver definida).

-U nome_do_usuário

Nome do usuário para se conectar.

-W

Força a solicitação da senha. Deve acontecer automaticamente se o servidor requerer autenticação por senha.


Exemplos:

$ pg_restore -d bd_novo bd.tar

http://www.postgresql.org/docs/9.2/static/app-pgrestore.html

[MySQL] – Habilitando acesso remoto ao servidor

Dica antiga que de vez em quando é necessário relembrar, deste modo irei deixar registrado aqui para não ter que ficar procurando no google sempre que precisar.

Executar todos os passos abaixo como root:
1 – Edite o arquivo:
/etc/mysql/my.cnf

2 – Altere a seguinte linha:
bind-address = 127.0.0.1
Deixando assim:
bind-address = 0.0.0.0
3 – Reinicie o Mysql
# /etc/init.d/mysql restart
4 – Vamos agora dar GRANT no usuário root, logue no mysql:
# mysql -u root -p
5 – Após se logar, digite o seguinte comando:
GRANT ALL ON *.* TO root@’%’ IDENTIFIED BY ‘sua_senha’;
Dessa forma você libera o acesso ao seu servidor Mysql vindo de qualquer máquina externa, caso queira liberar somente o acesso da sua máquina, é só verificar qual é seu IP e entrar com o comando:
GRANT ALL ON *.* TO root@’192.168.0.2′ IDENTIFIED BY ‘sua_senha’;
6. Após isso, basta dar uma reiniciada novamente no Mysql e realiazar a conexão remota.
# /etc/init.d/mysql restart
====================================================
Caso você queira desfazer o acesso remoto é bem simples também.
1 – Altere a seguinte linha:
bind-address = 0.0.0.0
Deixando assim:
bind-address = 127.0.0.1
2. Logue no Mysql:
# mysql -u root -p
3. Delete todos os privilégios remotos:
DELETE FROM mysql.user WHERE User = ‘root’ AND Host = ‘%’;
FLUSH PRIVILEGES;
4. Reinicie o Mysql e pronto, não estará mais acessível remotamente.
Fonte:
http://jf.eti.br/habilitando-acesso-remoto-ao-servidor-mysql/