2011-02-07 18 views
7

Estoy buscando diferentes formas de configurar Doctrine 2 para usar las conexiones maestro/esclavo usando MySQL. La configuración sería para que haya una base de datos maestra con múltiples esclavos. Todas las instrucciones SELECT deben provenir de un esclavo vivo al azar y cualquier instrucción UPDATE, INSERT, DELETE siempre se delegará en la conexión maestra.Doctrine 2 conexiones Maestro/Esclavo

¿Alguien ha configurado Doctine 2 de esta manera o tiene alguna idea sobre cómo abordarlo?

Respuesta

0

Por lo que yo sé que no hay soporte integrado para esto en Doctrina 2.

Realmente parece como si (al menos con MySQL), este problema va a ser resuelto en última instancia a otra parte. Ya sea en mysql_proxy, o por medio de un trabajo muy reciente con mysqlnd (la extensión MySQL nativa controlador para PHP)

Dado que ninguno de los que están listas para su (aunque mysql_proxy podría ser), su única opción inmediata es, por desgracia, para iniciar mirando el Doctrine DBAL, y ampliando las clases incorporadas para manejar las cosas inteligentemente, lo que significa que podría ser una buena idea detectar si la solicitud actual ha realizado alguna operación de escritura , y luego forzar cualquier lectura posterior para usar el maestro , evitando cualquier problema relacionado con el retraso de replicación.

Afortunadamente, veremos una solución más formal del equipo de Doctrine en los próximos 6-12 meses. Pero si lo necesita ahora, es DIY, AFAIK.

+0

Al final he optado por implementar nuestro propio envoltorio de conexión que aparece haber hecho el truco Espero que D2 desarrolle oficialmente la función en una versión posterior. – Kevin

7

Doctrine2 ahora tiene un MasterSlaveConnection en el espacio de nombres \ Doctrine \ DBAL \ Connections.

EDIT: Dont leer a continuación a menos que esta pieza no funciona

No necesite un overloader más, las configuraciones DBAL tomarán los esclavos por sí mismo. p.ej.

connections: 
      default: 
       driver: %database_driver% 
       host:  %database_host% 
       dbname: %database_name% 
       user:  %database_user% 
       password: %database_password% 
       slaves: 
        slave1: 
         host:  %database_slave1% 
         dbname: %database_name% 
         user:  %database_user% 
         password: %database_password% 

Si el no trabaja más arriba, intente esto Algo simple

, sólo hay que poner las tuberías (|) entre cada host

default: 
       driver: %database_driver% 
       host:  %database_host%|%database_slave%|%database_slave2% 
       port:  3306 
       dbname: %database_name% 
       user:  %database_user% 
       password: %database_password% 
       wrapper_class: \Foo\Bar\Symfony\Doctrine\Connections\MasterSlave 


<?php 
namespace Foo\Bar\Symfony\Doctrine\Connections; 
use \Doctrine\DBAL\Connections\MasterSlaveConnection; 
use Doctrine\DBAL\Connection, 
     Doctrine\DBAL\Driver, 
     Doctrine\DBAL\Configuration, 
     Doctrine\Common\EventManager, 
     Doctrine\DBAL\Event\ConnectionEventArgs, 
     Doctrine\DBAL\Events, 
     Doctrine\DBAL\Cache\QueryCacheProfile; 

class MasterSlave extends MasterSlaveConnection 
{ 
     public function __construct(array $params, Driver $driver, Configuration $config = null, EventManager $eventManager = null) 
     { 
       $tempParams = array(
           'master' => array() 
           , 'slaves' => array() 
           , 'driver' => $params['driver'] 
           ); 
       $hosts = explode('|', $params['host']); 
       unset($params['host']); 
       foreach($hosts as $num => $host) 
       { 
         $params['host'] = $host; 
         if($num == 0) 
         { 
           $tempParams['master'] = $params; 
         } 
         else 
         { 
           $tempParams['slaves'][] = $params; 
         } 
       } 

       if(!isset($tempParams['master']['driver'])) 
         $tempParams['master']['driver'] = "pdo_mysql"; 

       foreach($tempParams['slaves'] as $k => $slave) 
       { 
         if(!isset($slave['driver'])) 
           $tempParams['slaves'][$k]['driver'] = "pdo_mysql"; 
       } 
       parent::__construct($tempParams, $driver, $config, $eventManager); 
     } 

     public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null) 
     { 
       try 
       { 
         return parent::executeQuery($query, $params, $types, $qcp); 
       } 
       catch(\Exception $e) 
       { 
         $logger = new \Uelib\Core\Logger(); 
         $message = $e->getMessage() . "\nSql: " . $query . "\nParams: \n" . print_r($params, true); 
         $logger->log($message); 
         throw $e; 
       } 
     } 
} 
+0

único problema es, no puedo entender cómo obtener Symfony para jugar bien con las configuraciones necesarias – Ascherer

+0

Ya no necesito esto !!!!, leer editar – Ascherer

+2

Podría ser hora de aceptar esto @Kevin ¿no? – alex88