Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Michel Kuguio

Pool de Conexões PDO.

Recommended Posts

Bom eu estava pensando em ter dois usuarios uma para leitura e outro para crud, assim tdos select iria usar em uma conexão e o resto na outra sendo que a conexão voltada para os selects ficaria aberto o tempo todo.

 

perguntando sobre isso na aba de DB o pessoal pediu para eu pesquisar sobre Pool de conexões, mas só estou achando tutorial de outras linguagens, e até encontrei um de PDO todo ingles... mas estou vendo se consigo intender como funciona e se entendo o algoritimo. se alguem tiver uma base para eu poder seguir de modelo eu agradeço.

 

mas fica uma pergunta - Deixo padrao fexando a abrindo conexao a cada chamado ou

Uma conexao aberta para leitura e uma padrao que só abre para alterar dados, ou faço esse pool?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Hum, acho que o PDO já faz esse trabalho para você, basta criar objeto PDO passando seus parametros. Mas olha, não tenho certeza desta afirmação.

 

Mas to percebendo que está complicando as coisas. Não é mais fácil somente criar seu objeto de conexão, e deixar a aplicação trabalhar normalmente? O PDO já faz tarefas de tratar conexões sem sobrecarregar o servidor.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom, antes de tudo, explique melhor o seu problema. Dessa forma, ficará mais fácil lhe ajudar.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não sou um expert em pool de conexão, e só conhecia o pool de impressão e sua origem para resolver um problema (condição de corrida). Então eu fui pesquisar.

Conforme estive pesquisando, você dependerá de configurações, tanto no SGBD como no PHP para utilizar de pool de conexão. Mais no SGBD, para falar a verdade.

 

Diferentemente de .NET, que possui pool de conexão, conforme eu li, o PHP não possui. Conforme poderá ler nessa Thread:

http://stackoverflow.com/questions/39753/connection-pooling-in-php

 

O PHP, possui ciclo de vida por execução. Você realiza a requisão, o servidor interpreta o PHP, realiza sua execução e devolve uma resposta. Após a resposta, tudo que foi utilizado, com pequenas exceções (sessions/cookies, pconnect e possivelmente mais), não existirá mais. O mesmo acontece com conexões com SGBD. Exceto a conexão pconnect, que sempre se mantem ativa. Entretanto, não é nenhum um pouco recomendável utilizar pconnect, pois o PHP, após a execução do script, elimina as conexões para liberar a banda do SGBD.

 

Apesar de pconnect, por alguns, serem considerados um Pool de conexão, ele não é. Entretanto, conforme poderá ver nos artigos abaixo da Oracle, se utilizado em conjunto com o SGBD, poderá sim, ser um pool de conexão.

https://blogs.oracle.com/opal/entry/highly_scalable_connection_poo

http://www.oracle.com/technetwork/topics/php/php-scalability-ha-twp-128842.pdf

 

A PDO realiza o encapsulamento da conexão, assim, durante a execução, você terá uma única conexão por instância da aplicação (se houver 2 usuários acessando o site/sistema, possuirá 2 conexões) e a utilizando durante toda a execução do script. O que é bastante recomendável.

 

Caso você deseje utilizar uma pconnect com PDO, você deve atribuir a constante ATTR_PERSISTENT. Seria o seguinte:

$conn = new PDO("mysql:host=localhost;dbname=basename", 'root' , 'password' , array(PDO::ATTR_PERSISTENT => true));

 

Mas não vejo uma real necessidade de um pool de conexão. É mais recomendado você se preocupar com a engenharia empregada no uso das classes e das conexões (quantidades absurdas de consultas), para consumir menos o servidor, do que se preocupar em criar um pool de conexão. Já trabalhei com aplicações grandes em PHP e não houve problemas com consultas excessivas, mas o seu SGBD deve possuir indexes conforme a quantidade de registros, isso é extremamente necessário.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Então o que eu disse a respeito do PDO fazer pool de conexões estão corretas, Gabriel Heming? Aliás, já li na documentação sobre essas constantes. :thumbsup:

Compartilhar este post


Link para o post
Compartilhar em outros sites

As informações estão quase corretas. A PDO, em conjunto com o SGBD, pode sim realizar o pool de conexão. Mas ela, por si só, não realiza. A PDO é um Façade, além de manter uma interface comum e simplificada, em relação aos SGBDs, ela realiza o encapsulamento da conexão. Mas somente isso, não é um pool.

 

Eu estive procurando uma definição concreta de pool. Mas todas que eu encontrei são um tanto confusas. Até onde eu entendo, pool, na computação, pode ser conceituado como uma estrutura do tipo fila, onde você adiciona processos e esses serão executados na ordem em que foram inseridos, exatamente como é uma fila de supermercado, quem entrou antes, será executado antes.

 

Apesar da programação "enfileirar" os scripts (exceto em treads), você envia uma requisição por vez ao SGBD. O SGBD processa em paralelo todas as requisições de cada conexão. No caso de você possuir 3 conexões e enviar 3 requisições, uma de cada vez, elas não serão respondidas em ordem de recebimento, como espera-se de um pool. A requisição que for executada mais rápido, terá a resposta primeiro, indiferente da ordem de envio.

 

Se você for testar com a impressora, envie um arquivo de 100 páginas e logo após, um arquivo de uma página. Como espera-se de um pool, você receberá primeiro a impressão de 100 páginas e logo após a impressão de uma página. Na PDO, sem as configurações necessárias entre PDO e SGBD, você recebera primeiro a que possuir a execução mais rápida.

Compartilhar este post


Link para o post
Compartilhar em outros sites

+1 pra ti. Diante disso, tive boas idéias aqui que não tinha pensado! :thumbsup:

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não sou um expert em pool de conexão, e só conhecia o pool de impressão e sua origem para resolver um problema (condição de corrida). Então eu fui pesquisar.

Conforme estive pesquisando, você dependerá de configurações, tanto no SGBD como no PHP para utilizar de pool de conexão. Mais no SGBD, para falar a verdade.

 

Diferentemente de .NET, que possui pool de conexão, conforme eu li, o PHP não possui. Conforme poderá ler nessa Thread:

http://stackoverflow.com/questions/39753/connection-pooling-in-php

 

O PHP, possui ciclo de vida por execução. Você realiza a requisão, o servidor interpreta o PHP, realiza sua execução e devolve uma resposta. Após a resposta, tudo que foi utilizado, com pequenas exceções (sessions/cookies, pconnect e possivelmente mais), não existirá mais. O mesmo acontece com conexões com SGBD. Exceto a conexão pconnect, que sempre se mantem ativa. Entretanto, não é nenhum um pouco recomendável utilizar pconnect, pois o PHP, após a execução do script, elimina as conexões para liberar a banda do SGBD.

 

Apesar de pconnect, por alguns, serem considerados um Pool de conexão, ele não é. Entretanto, conforme poderá ver nos artigos abaixo da Oracle, se utilizado em conjunto com o SGBD, poderá sim, ser um pool de conexão.

https://blogs.oracle.com/opal/entry/highly_scalable_connection_poo

http://www.oracle.com/technetwork/topics/php/php-scalability-ha-twp-128842.pdf

 

A PDO realiza o encapsulamento da conexão, assim, durante a execução, você terá uma única conexão por instância da aplicação (se houver 2 usuários acessando o site/sistema, possuirá 2 conexões) e a utilizando durante toda a execução do script. O que é bastante recomendável.

 

Caso você deseje utilizar uma pconnect com PDO, você deve atribuir a constante ATTR_PERSISTENT. Seria o seguinte:

$conn = new PDO("mysql:host=localhost;dbname=basename", 'root' , 'password' , array(PDO::ATTR_PERSISTENT => true));

 

Mas não vejo uma real necessidade de um pool de conexão. É mais recomendado você se preocupar com a engenharia empregada no uso das classes e das conexões (quantidades absurdas de consultas), para consumir menos o servidor, do que se preocupar em criar um pool de conexão. Já trabalhei com aplicações grandes em PHP e não houve problemas com consultas excessivas, mas o seu SGBD deve possuir indexes conforme a quantidade de registros, isso é extremamente necessário.

entao eu estou em um projeto, fiz uma classe de conexão q é a pai, e duas subclasse uma da da estrutura da query e otra de crud, uma extendendo a outra.

 

porem a cada Objeto ele faz uma nova conexão, e no final finaliza a mesma.. só que eu estava pensando isso nao iria pejudicar o desempenho do site?

 

Desculpe as perguntas mas é que o POO eu aprendi recentemente, antes eu deixar uma conexão para o site geral.. mas pelo q vi no POO a conexão é iniciada a cada objeto.

 

outra coisa é que ta me deixando P. é que meu local host ta muito lento aí eu fico na duvida se tem algo errado com o site.. mas creio q é compatibilidade do wamp mesmo.

 

esqueci de comentar nao entendo muito do pconect

minha classe de conexão esta assim:

<?php
class Conexao{

//DADOS DA CONEXÃO
protected $_conection;
protected $_conecta;
const _host = 'localhost';		//NOME DO SERVER
const _db = 'site';  //NOME DO USUÁRIO
const _user	= 'root';			//NOME DO BANCO DE DADOS
const _pass = 'xxxx';				//SENHA

/*--------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------*/

//FUNÇÃO CONSTRUTORA
public function __construct(){

		//INICIA A CONEXAO
		$this->Start();

}//FECHA FUNÇÃO CONSTRUTORA

/*--------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------*/	

//METODO DE CONEXAO PDO
protected function Start(){

	//CONEXÃO
	$this->_conection = 'mysql:host='.self::_host.';dbname='.self::_db;

	if(!isset($this->_conecta) or isset($this->_conecta)&&$this->_conecta==null){
	//LÓGICA PHP
		try{
				$this->_conecta = new PDO($this->_conection,self::_user,self::_pass);
				$this->_conecta->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
		}catch(PDOexception $error){
				echo $error->getMessage();
		}
	}

}//FECHA FUNÇÃO START

/*--------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------*/	
public function __destruct(){
		$this->_conecta=NULL;
		unset($this->_conecta);
		}

}//FECHA CLASSE

?>

 

no caso para funcionar esse Pconect eu deveria deixar assim?

//METODO DE CONEXAO PDO
protected function Start(){

	//CONEXÃO
	$this->_conection = 'mysql:host='.self::_host.';dbname='.self::_db;

	if(!isset($this->_conecta) or isset($this->_conecta)&&$this->_conecta==null){
	//LÓGICA PHP
		try{
				$this->_conecta = new PDO($this->_conection,self::_user,self::_pass,array(
   PDO::ATTR_PERSISTENT => true
));					
				$this->_conecta->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
		}catch(PDOexception $error){
				echo $error->getMessage();
		}
	}

}//FECHA FUNÇÃO START

Minhas classe fica como extend dela, ou devo fazer diferente?

se tiver algo que eu esteja errando.. ou que eu poderia fazer melhor me avisem, por favor.

 

 

e só para explicar como eta funcionando ele:

/// exemplo se eu estancio uma objeto assim ele cria uma conexão nova e utiliza durante o processo do objeto;
$teste = new tabelaUm;
$teste->SelectbyID($x)
$countTeste=$teste->getCount();
$if($countTeste<3){
$teste->Insert($Anuncio,$usuario);
$teste->IDdo Anuncio();
}
///se eu preciso fazer a mesma coisa com outra sub classe ele cria uma nova conexao mas a antiga ja foi fexada.
$teste = new tabelaDois;
$teste->SelectbyID($x)
$countTeste=$teste->getCount();
$if($countTeste<3){
$teste->Insert($Anuncio,$usuario);
$teste->IDdo Anuncio();
}

//nao seria mais vantajoso se ele fizer-se só uma conexão usar-se durante todos os objetos e no final fexa-se a mesma?

Compartilhar este post


Link para o post
Compartilhar em outros sites

porem a cada Objeto ele faz uma nova conexão, e no final finaliza a mesma.. só que eu estava pensando isso nao iria pejudicar o desempenho do site?

 

Sim, muito.

 

Minhas classe fica como extend dela, ou devo fazer diferente?

se tiver algo que eu esteja errando.. ou que eu poderia fazer melhor me avisem, por favor.

 

Deve fazer diferente. Utilize composição e agregação

 

A classe conecta, você utiliza de composição para o uso da PDO, o que está correto. Para seu objetos de consulta (model/DAO/ORM) utilize de agregação.

 

Por exemplo, eu posso o objeto de acesso a dados UsuarioDAO, ele serve para somente para acessar os dados de um usuário no SGBD e utiliza uma conexão. Ele não é uma conexão e não será somente ele a utilizar conexão. Isso já define que não estamos falando de herança(extends) e nem de composição. Isso é uma agregação.

 

Vamos ao meu DAO com base na sua conecta. Não vou muito afundo, pois o João Batista Neto da uma excelente aula neste tópico

class UsuarioDAO {
   private $connection;

   public function __construct(Conexao $conexao) {
       $this->connection = $conexao;
   }

   public function select() {
       /** código referente ao select **/
   }
}

 

para o seu uso, basta passar a Conexao e usufruir dela:

$conexao = new Conexao();
$usuarioDAO = new UsuarioDAO($conexao);

 

Você poderá utilizar um Registry, em conjunto, para manter disponível essa conexão em qualquer lugar da aplicação, evitando criar várias conexões.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sim, muito.

 

 

 

Deve fazer diferente. Utilize composição e agregação

 

A classe conecta, você utiliza de composição para o uso da PDO, o que está correto. Para seu objetos de consulta (model/DAO/ORM) utilize de agregação.

 

Por exemplo, eu posso o objeto de acesso a dados UsuarioDAO, ele serve para somente para acessar os dados de um usuário no SGBD e utiliza uma conexão. Ele não é uma conexão e não será somente ele a utilizar conexão. Isso já define que não estamos falando de herança(extends) e nem de composição. Isso é uma agregação.

 

Vamos ao meu DAO com base na sua conecta. Não vou muito afundo, pois o João Batista Neto da uma excelente aula neste tópico

class UsuarioDAO {
   private $connection;

   public function __construct(Conexao $conexao) {
       $this->connection = $conexao;
   }

   public function select() {
       /** código referente ao select **/
   }
}

 

para o seu uso, basta passar a Conexao e usufruir dela:

$conexao = new Conexao();
$usuarioDAO = new UsuarioDAO($conexao);

 

Você poderá utilizar um Registry, em conjunto, para manter disponível essa conexão em qualquer lugar da aplicação, evitando criar várias conexões.

perfeito, mas vem uma duvia sobre esse registro... ele salva o arquivo aonde?

tipo teoricamente ele é a mes coisa do q você passou acima.. nao é?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sim, muito.

 

 

 

Deve fazer diferente. Utilize composição e agregação

 

A classe conecta, você utiliza de composição para o uso da PDO, o que está correto. Para seu objetos de consulta (model/DAO/ORM) utilize de agregação.

 

Por exemplo, eu posso o objeto de acesso a dados UsuarioDAO, ele serve para somente para acessar os dados de um usuário no SGBD e utiliza uma conexão. Ele não é uma conexão e não será somente ele a utilizar conexão. Isso já define que não estamos falando de herança(extends) e nem de composição. Isso é uma agregação.

 

Vamos ao meu DAO com base na sua conecta. Não vou muito afundo, pois o João Batista Neto da uma excelente aula neste tópico

class UsuarioDAO {
   private $connection;

   public function __construct(Conexao $conexao) {
       $this->connection = $conexao;
   }

   public function select() {
       /** código referente ao select **/
   }
}

 

para o seu uso, basta passar a Conexao e usufruir dela:

$conexao = new Conexao();
$usuarioDAO = new UsuarioDAO($conexao);

 

Você poderá utilizar um Registry, em conjunto, para manter disponível essa conexão em qualquer lugar da aplicação, evitando criar várias conexões.

perfeito, mas vem uma duvida sobre esse registro... ele salva o arquivo aonde?

tipo teoricamente ele é a mes coisa do q você passou acima.. nao é?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não entendi muito bem a sua pergunta, mas para eventuais esclarecimentos sobre o Registry, vai encontrar nessa thread:

http://forum.imasters.com.br/topic/463107-pdo-registry-design-pattern-phpoo/page__view__findpost__p__1896377

Compartilhar este post


Link para o post
Compartilhar em outros sites

Excelente explicação do Gabriel. No meu caso, eu faço o seguinte:

 

<?
class UserGateway{

    private $stm;

    public function __construct(){
         $this->stm = new Factory(new StatementPDOMySQL());
         #### Aqui, posso agregar outros objetos, tais como:
         # StatementPDOPosgreeSQL, 
         # StatementMySQL, StatementPostgreSQL (para functions nativas)
    }

    public function dataSelect(){
         #### code ####
         return $this->stm->executeQuery(array(...));
    }

}
?>

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não entendi muito bem a sua pergunta, mas para eventuais esclarecimentos sobre o Registry, vai encontrar nessa thread:

http://forum.imasters.com.br/topic/463107-pdo-registry-design-pattern-phpoo/page__view__findpost__p__1896377

cara esta apresentando esse erro:

Fatal error: Call to undefined method Conexao::prepare() in D:\wamp\www\site_perfeito\Protected\Library\Padroes\BaseBD.php on line 41

nao sei pq, pque testei e esta pegando a conexao certinho; =S

Compartilhar este post


Link para o post
Compartilhar em outros sites

Na verdade, pra você usar o prepare, é necessário acessá-lo pelo objeto que cria sua conexão, exemplo:

 

<?

class Conn{

     private $conn;

     public function connect($sql){
         $this->conn = new PDO('...');
         $prepare = $this->conn->prepare($sql);    

         try{
             $prepare->execute();
         }catch(PDOException $e){
              echo $e->getMessage();
         }
     }

}

?>

Compartilhar este post


Link para o post
Compartilhar em outros sites

cara esta apresentando esse erro:

Fatal error: Call to undefined method Conexao::prepare() in D:\wamp\www\site_perfeito\Protected\Library\Padroes\BaseBD.php on line 41

nao sei pq, pque testei e esta pegando a conexao certinho; =S

achei o erro mesmo retornando a variável ele estava pegando o objeto inteiro;

 

Na verdade, pra você usar o prepare, é necessário acessá-lo pelo objeto que cria sua conexão, exemplo:

 

<?

class Conn{

     private $conn;

     public function connect($sql){
         $this->conn = new PDO('...');
         $prepare = $this->conn->prepare($sql);    

         try{
             $prepare->execute();
         }catch(PDOException $e){
              echo $e->getMessage();
         }
     }

}

?>

 

sim.. tava tudo certo.. mas nao tava passando só a variavel de conexao tava passando o objeto inteiro.. aí eu corrigi isso. xD

 

Não entendi muito bem a sua pergunta, mas para eventuais esclarecimentos sobre o Registry, vai encontrar nessa thread:

http://forum.imasters.com.br/topic/463107-pdo-registry-design-pattern-phpoo/page__view__findpost__p__1896377

entao tipo esse registre funciona como um backup porem funciona só na aplicação local, se você atualizar a pagina ou ir para outra será criado uma nova conexão e como esta ativo o Persist, ela nao desligará correto?

 

a pergunat se teria como fazer algo para usar durante todo processo de navegação só uma conexão.

Compartilhar este post


Link para o post
Compartilhar em outros sites

so você deseje utilizar uma pconnect com PDO, você deve atribuir a constante ATTR_PERSISTENT. Seria o seguinte:

$conn = new PDO("mysql:host=localhost;dbname=basename", 'root' , 'password' , array(PDO::ATTR_PERSISTENT => true));

Cara hoje acordei e pensei uma coisa tipo, se ele vai persistir na conexao eu poderia deixar já como extend das outras

pelo fato de manter uma só conexao. concorda?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Apesar de estarmos falando sobre pool de conexão utilizando pconnect, preciso lhe "falar umas verdades".

 

1º - Não é recomendável o uso de conexões persistentes, evite-as (com ou sem pool, não é recomendável);

2º - Não é só o caso de duplicar a conexão (ou não). Também duplicará as classes, criará redundâncias inúteis e maior consumo de memória;

3º - Ela não é uma conexão. Nesse caso não cabe à herança;

4º - Leia sobre Liskov Substitution Principle.

 

 

A herença (extends) cabe quando uma sub-classe é a super-classe com "algo a mais".

 

O exemplo clássico é de uma pessoa.

- Pessoa é a classe base;

- PessoaFisica e PessoaJuridica são as especializações;

- Ambas são Pessoa (class). Possuem tudo que uma Pessoa possui e mais suas peculiaridades.

 

Um model/ORM/DAO não é uma conexão, somente utiliza uma. Portanto, não cabe à herança.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.