2012-02-08 16 views

risposta

1

L'approccio migliore è quello di avvolgere la creazione dell'istanza DOP in un Singleton (cioè MyPDOFactory) che memorizza sia l'istanza e il tempo della creazione, in questo modo, è possibile riutilizzare o ricrearla dopo un TTL è stato raggiunto (2 o 3 secondi è più che sufficiente per la maggior parte delle applicazioni). Dovrai semplicemente chiamare MyPDOFactory :: get() per ottenere un PDO valido che puoi utilizzare per preparare il PDOStatement, ma assicurati di eseguirlo il prima possibile.

+0

Capisco la tua idea, ma dovresti davvero aggiungere codice alla tua risposta. –

+0

Cosa succede se stai eseguendo una serie di query che sono a) transazionali, eb) accade più tempo del TTL? – GordonM

-1

penso che questo possa aiutarti.

/* 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

La tua risposta è inutile per riconnettersi dopo il timeout. Nel blocco try è necessario inserire il codice della query e, se la connessione è andata, ricollegarsi nel blocco catch. E poi in qualche modo lanciare nuovamente la query ... –

0

riconnessione ad un DB dopo un errore è in realtà un problema molto più complicato di quanto non sarebbe sembrare a prima vista.

mia prima idea era di scrivere una semplice classe wrapper per PDO che proxy metodi su un oggetto PDO interno e può gestire connessioni errori si:

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; 
       } 
      } 
     } 
    } 
} 

Poiché questa classe estende DOP, può essere utilizzato ovunque la può essere usata una classe generica DOP.

Come si può vedere, questo approccio vi darà un paio di tentativi prima che il metodo exec() si arrende, che permette la riconnessione dopo errori transitori (questo è solo per la dimostrazione e manca di alcune funzionalità di una reale implementazione avrebbe bisogno, come un backoff tra tentativi, adeguata registrazione degli errori, ecc.). Questo approccio richiede anche che tu controlli le specifiche dell'eccezione PDO generata in base al fatto che non vuoi che cose come gli errori di sintassi MySQL causino il reset della connessione e un tentativo di nuovo tentativo. Vuoi solo che accada su cose come "Il server è andato via".

Come si può anche vedere, l'implementazione di tutti i metodi PDO proxy diventerebbe un lavoro ingrato, anche se come si deve fare solo una volta è probabilmente la pena investire lo sforzo per farlo.

C'è un problema molto più grande, che è praticamente un problema universale per qualsiasi codice che parla con un database, non solo PDO. Cosa succede se una connessione viene persa nel mezzo di una transazione? Non vuoi che il tuo script si ricolleghi e riprenda da dove era stato interrotto in quel caso, perché tutto il lavoro che hai svolto fino all'ultimo commit sarebbe andato perduto, e le probabilità sono che non avrebbe senso riprendere logicamente dopo aver ricollegato, dovresti ricominciare da capo. Quindi probabilmente vorrai ricominciare da capo l'intero script e tentare una riconnessione non avrebbe alcun senso. Questo è probabilmente il motivo per cui mySQLI supporta la riconnessione ma PDO no.

Se lo script fa solo legge o scrive non di transazione, quindi l'approccio di cui sopra ha ancora un valore, ma non appena si lancia transazioni nel mix si sta effettivamente molto meglio non tentare di riconnettersi.

Problemi correlati