2012-02-08 17 views

Respuesta

1

El mejor enfoque es envolver la creación de la instancia PDO en un singleton (es decir, MyPDOFactory) que almacena tanto la instancia como la hora de creación, de esta manera, puede reutilizarlo o recrearlo después de que se haya alcanzado un TTL (2 o 3 segundos es más que suficiente para la mayoría de las aplicaciones). Simplemente tendrá que llamar a MyPDOFactory :: get() para obtener un PDO válido que puede usar para preparar PDOStatement, solo asegúrese de ejecutarlo lo antes posible.

+0

Entiendo su idea, pero realmente debería agregar código a su respuesta. –

+0

¿Qué sucede si está ejecutando un conjunto de consultas que son a) transaccionales, yb) pasan más tiempo que el TTL? – GordonM

-1

Creo que esto puede ayudarlo.

/* Your Database Name */ 
    $dbname = 'mydatabase'; 

    /* Your Database User Name and Passowrd */ 
    $username = 'root'; 
    $password = 'password'; 

    try { 
     /* Establish the database connection */ 
     $conn = new PDO("mysql:host=localhost;dbname=$dbname", $username, $password); 
     $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    /* your code goes here*/ 
} catch(PDOException $e) { 
     echo 'ERROR: ' . $e->getMessage(); 
    } 
    //mysql_close($conn); 

    $conn=null; 
+0

Su respuesta es inútil para volver a conectar después de que se agote el tiempo de espera. En el bloqueo de prueba, debe colocar el código de consulta y, si la conexión no existe, reconectarse en el bloque catch. Y luego, de alguna manera, lanza la consulta de nuevo ... –

0

Volver a conectar a un DB después de un error es en realidad un problema mucho más complicado de lo que parecería en un principio.

Mi primera idea era escribir una clase de contenedor simple para PDO que los proxies métodos sobre un objeto PDO interna y puede manejar conexión en sí errores:

class BetterPDO extends PDO 
{ 
    private $realPDO = NULL; 
    private $dsn  = ""; 
    private $username = ""; 
    private $password = ""; 
    private $options = []; 

    public function __construct ($dsn, $username = "", $password = "", $options = []) 
    { 
     $this -> dsn = $dsn; 
     $this -> username = $username; 
     $this -> password = $password; 
     $this -> options = $options; 
    } 

    private function getRealPDO() 
    { 
     if (is_null ($this -> realPDO)) 
     { 
      $this -> realPDO = new PDO ($this -> dsn, $this -> username, $this -> password, $this -> options); 
     } 
     return $this -> realPDO; 
    } 

    // We're only implementing exec for brevity but you have to do this for all public methods of PDO 
    public function exec ($sql) 
    { 
     $retries = 0; 
     while (true) 
     { 
      try 
      { 
       return $this -> getRealPDO() -> exec ($sql); 
      } 
      catch (PDOException $ex) 
      { 
       $this -> realPDO = NULL; 
       if (++$retries > 5) 
       { 
        // We've passed our retry limit 
        throw $ex; 
       } 
      } 
     } 
    } 
} 

Como esta clase extiende DOP, que puede ser utilizado en cualquier lugar del se puede usar una clase PDO genérica.

Como puede ver, este enfoque le dará algunos reintentos antes de que el método exec() ceda, permitiendo la reconexión después de errores transitorios (esto es solo para demostración y carece de algunas características que una implementación real necesitaría, como retroceso entre reintentos, registro de errores adecuado, etc.). Este enfoque también requeriría que verifique los detalles de la excepción PDO lanzada sobre la base de que no desea que cosas como los errores de sintaxis de MySQL hagan que se restablezca la conexión y se intente de nuevo. Solo quiere que suceda en cosas como "El servidor se ha ido".

Como también puede ver, la implementación de todos los métodos de PDO con proxy sería una tarea ardua, aunque solo tiene que hacerlo una vez que probablemente valga la pena invertir el esfuerzo para hacerlo.

Aunque hay un problema mucho más grande, que es prácticamente un problema universal para cualquier código que se comunica con una base de datos, no solo con PDO. ¿Qué sucede si se pierde una conexión en medio de una transacción? No quiere que su script se vuelva a conectar y retome donde lo dejó en ese caso porque todo el trabajo que ha realizado hasta la última confirmación se habrá perdido, y es posible que no tenga sentido lógico reanudarlo. después de volver a conectar, tendrías que comenzar de nuevo. Por lo tanto, probablemente solo quiera que todo el script comience nuevamente, y intentar reconectarlo no tendría ningún sentido. Esta es probablemente la razón por la cual mySQLI admite la reconexión pero PDO no lo hace.

Si su script solo lee, o escritura no transaccional, entonces el enfoque anterior todavía tiene valor, pero tan pronto como se lanzan transacciones a la mezcla, en realidad está mucho mejor sin intentar reconectar.

Cuestiones relacionadas