2014-09-23 25 views
6

Orada zaten bu konuda twoquestions olmuştur, ama hiç kimse aslında soruya cevap vardır.PDO: Bağlantının etkin olup olmadığını nasıl kontrol edelim, gerçek mi?

ben bağlantısı (eğer PDO::ERRMODE_EXCEPTION etkinleştirmek varsayarak) başarısız olursa PDO bir istisna durumu biliyorum ama bir bağlantı hala aktif, potansiyel saat sonra ise test etmek istiyorum.

Uzun koşu senaryo var ve bir süre bunu zaman aşımına sonra. Teorik olarak ben PDO::ATTR_TIMEOUT ile zamanın bu miktarı artırabilir ama temelde ben aktif bir bağlantı bana geri veren bir fonksiyon yazmak istiyorum - bu varsa ya zaten kurulmuş oldu ve veya zaman aşımına olmadıysa varolan bir bağlantıyı yeniden bağlayın .

Sadece SELECT 1 yapmak durum yakalamak ve yeniden bağlamak gerekir mi? Yoksa daha güzel bir yolu var mı?

+1

Bir yanıt yayınlanmıştır ve daha hoş bir şekilde, benim kötü olup olmadığını soran sorunuzu Cevabımı koymak farkında değildi. “SELECT 1” yöntemini kullanarak, IIRC olarak, PDO içinde gerçek bir “ping” yöntemi yoktur. –

+0

Ben çok benzer bir senaryo var çünkü ben çok umutlu bir şekilde bu soruyu izliyor olacağını isterim ** gerçekten ** hoş bir çözüm bulunmasını istiyoruz. – castis

+1

bir süre web'de arama Been ve ben bu siteyi buldum: http://brady.lucidgene.com/2013/04/handling-pdo-lost-mysql-connection-error/ bu konuda bilgim bir sağlamak için yeterli değildir şık cevap ama ʰᵈˑ @ ilginç – icecub

cevap

7

MySQL protokolü bu amaç için özel bir komut COM_PING destekler ve C API göndermek için bir çağrı mysql_ping() sahiptir. Bu, bağlantının aktif olup olmadığını sınar. Bağlantı MYSQL_OPT_RECONNECT ile oluşturulmuşsa

, otomatik (https://dev.mysql.com/doc/refman/5.6/en/auto-reconnect.html) bağlar. PDO geçerli sürümünü kullanıyorsanız

Maalesef bu özelliklerin hiçbiri desteklenir. Özel sorguları değil, yalnızca SQL sorgu dizelerini gönderebilirsiniz. Ve şimdi PDO, avantajlarına sahip ancak yeniden bağlanma seçeneğini desteklemeyen mysqlnd sürücüsünü kullanıyor. Yani sorun zaten bir moot.

SELECT 1 gibi bir "kukla" sorgusu çıkarmaya çalışmaktan daha özel bir çözüm bilmiyorum, istisnayı yakalayın ve 2006 hata kodu (sunucu kaybolduysa) yeniden bağlanın.

Canlı bir bağlantı için uygulama kodu getConnection çağıran her bir tekil sizin db bağlantısını tutmak için sınıf, ve testi oluşturabilir(). İşte test bir örnek:

class DB 
{ 
    protected static $pdo = null; 

    public static function getConnection() { 
     // initialize $pdo on first call 
     if (self::$pdo == null) { 
      self::init(); 
     } 

     // now we should have a $pdo, whether it was initialized on this call or a previous one 
     // but it could have experienced a disconnection 
     try { 
      echo "Testing connection...\n"; 
      $old_errlevel = error_reporting(0); 
      self::$pdo->query("SELECT 1"); 
     } catch (PDOException $e) { 
      echo "Connection failed, reinitializing...\n"; 
      self::init(); 
     } 
     error_reporting($old_errlevel); 

     return self::$pdo; 
    } 

    protected static function init() { 
     try { 
      echo "Opening new connection...\n"; 
      self::$pdo = new PDO('mysql:host=huey;dbname=test', 'root', 'root'); 
      self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
     } catch (PDOException $e) { 
      die($e->getMessage()); 
     } 
    } 
} 

böyle kullanın:

echo "Query for 2:\n"; 
$pdo = DB::getConnection(); 
echo $pdo->query("SELECT 2")->fetchColumn() . "\n"; 

echo "\nSleeping 10 seconds...\n"; 
sleep(10); /* meanwhile I use another window to KILL the connection */ 
echo "\n"; 

echo "Query for 3:\n"; 
$pdo = DB::getConnection(); 
echo $pdo->query("SELECT 3")->fetchColumn() . "\n"; 

Çıktı:

Query for 2: 
Opening new connection... 
Testing connection... 
2 

Sleeping 10 seconds... 

Query for 3: 
Testing connection... 
Connection failed, reinitializing... 
Opening new connection... 
3 

Bunu bağlantısı başarısız olduğunu algılar ve reinitializes olduğunu görebilirsiniz.

İlgili konular