Visualizzazione risultati 1 fino 5 di 5

Discussione: Connection failed: SQLSTATE[HY000] [1040] Too many connections?

  1. #1
    Guest

    Unhappy Connection failed: SQLSTATE[HY000] [1040] Too many connections?

    E' la prima volta che mi succede questo errore (vedi titolo) e non capisco davvero il motivo, pensare che ho registrato l'account e usato solo da un paio di giorni.

    Vi passo un pò di codice che stavo trascrivendo, magari se è solo un problema di codice, potete aiutarmi a trovare il problema, perché io non riesco a comprendere il motivo delle immense chiamate:

    Codice PHP:
    #update BOSSWORLD
    $CH = new CHARACTER($_COOKIE["public"]);
    $B = new MOBS();
    $BW = new BOSSWORLD();
    $BOSS_INFO = CONF::dejson($BW->json);
    $MENAGE = new MENAGE();
    if(
    $_REQUEST["w"] == "hp")
    {
    $B->update($BOSS_INFO["id"],$_REQUEST["w"],$_REQUEST["p"]);
    QUesta è la funzione update della classe MOBS:
    Codice PHP:
    public function update($i,$w,$p,$reset=null){
    $CH = new CHARACTER($_COOKIE["public"]);
    $STAT = $this->listMobs("3","id",$i);
    if(
    $reset!=null&&$reset){
    $query = "Update mobs set $w = :h where id = :i";
    }
    else{
    $query = "Update mobs set $w = $w+:h where id = :i";
    }
    $HAN = CONF::PDO()->prepare($query);
    $formula_damage = $this->formula($i,"damage");
    if(
    $HAN->execute(
    array(

    "h"=>CONF::escape(-$formula_damage),
    "i"=>CONF::escape($i)
    )
    )){
    if(
    $p == "world"){
    $this->updateLastBoss($i);
    $BWD = new BOSSWORLD_DAMAGE();
    $BWD->update($i);

    $exp_earn = $this->formula($i,"exp");
    $gold_earn = $this->formula($i,"gold");
    $this->update($i,"exp",-$exp_earn);
    $this->update($i,"gold",-$gold_earn);
    #controllo hp se scende sotto a 0 lo reputo 0
    $query = "SELECT exp,gold from mobs where id = :id";
    $PDO = CONF::PDO()->prepare($query);
    $PDO->execute(array("id"=>$i));
    $PDO = null;
    $FFORCONTROLLO0EXPEGOLD = $HAN->fetch(PDO::FETCH_OBJ);
    if(
    $FFORCONTROLLO0EXPEGOLD->exp <= 0) $this->update($i,"exp",0,$p,true);
    if(
    $FFORCONTROLLO0EXPEGOLD->g <= 0) $this->update($i,"g",0,$p,true);
    }

    $HAN = null;
    return
    true;
    }
    else{
    echo
    $HAN->errorInfo()[2];
    $HAN = null;
    return
    false;
    }
    }
    Codice PHP:
    class BOSSWORLD_DAMAGE extends MOBS {
    public function
    update($idm){
    $formula_damage = $this->formula($idm,"damage");
    $exp_earn = $this->formula($idm,"exp");
    $gold_earn = $this->formula($idm,"gold");
    $query = "SELECT * FROM bossworld_damage where id_player = :id";
    $HAN = CONF::PDO()->prepare($query);
    $HAN->execute(array("id"=>$CH->id));
    if(
    $HAN->fetchColumn() == 0){
    $query = "INSERT INTO bossworld_damage(id_player,damage,exp_earn,gold_earn) VALUES(:id,:d,:e,:g)";
    $PDO = CONF::PDO()->prepare($query);
    $PDO->execute(array("id"=>$CH->id,"d"=>$formula_damage,"e"=>$exp_earn,"g"=>$gold_earn));
    $PDO = null;
    }
    else{
    $query = "UPDATE bossworld_damage set damage = damage+:d, exp_earn = exp_earn+:e, gold_earn = gold_earn+:g where id_player = :id";
    $PDO = CONF::PDO()->prepare($query);
    $PDO->execute(array("id"=>$CH->id,"d"=>$formula_damage,"e"=>$exp_earn,"g"=>$gold_earn));
    $PDO = null;
    }
    $HAN = null;
    }
    }
    Ultima modifica di praedo : 13-01-2018 alle ore 22.27.16

  2. #2
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    L'errore è causato dal numero di connessioni contemporaneamente aperte verso la base di dati.

    Nel codice che hai mostrato mancano le parti più rilevanti, ovvero quelle in cui gestisci l'apertura e, soprattutto, la chiusura delle connessioni.

    Dal codice sembra che tu intenda utilizzare la classe CONF come un singleton: dovresti aprire la connessione una sola volta, eventualmente in maniera lazy contestualmente alla prima richiesta di interrogazione della base di dati, e fare in modo che la connessione venga chiusa quando non più necessaria (anziché al termine dello script). Utilizzando metodi statici come stai facendo, direi che l'unico modo è chiudere manualmente la connessione CONF::PDO = null;, meglio ancora sarebbe prevedere un metodo close o analogo.

    Ciò detto, dovresti tenere traccia delle connessioni che apri e chiudi. Prova a produrre un file di log in modo da farti un'idea della quantità reale di traffico a cui vai incontro.

    Tieni anche conto dei limiti fisici dell'approccio che hai scelto di usare: ad occhio sembra il codice di un gioco online, magari multigiocatore, quindi se 200 giocatori si connettono contemporaneamente al server sicuramente vai ad esaurire il numero di connessioni disponibili.

  3. #3
    Guest

    Predefinito

    Allora sì, io apro le connessioni
    Codice PHP:
    class CONF{

    public static function
    PDO(){

    try {

    return new
    PDO("mysql:host=".HOST.";dbname=".DBNAME,DBUSER,DBPASSW);

    } catch (
    PDOException $e) {

    return
    "Connection failed: " . $e->getMessage();

    }

    }
    E cavolo sì, ne fa tante di connessioni, ho creato il file di log come mi hai consigliato: https://praedo.altervista.org/log.text

    E per curiosità, qual'è il massimo di connessioni che Altervista ti permette di fare? Perché ora vedrò di sistemare completamente il codice, in modo da chiudere sempre dove necessario le chiamate, e migliorare i codici per farlo più veloce.

  4. #4
    mzanella non è connesso AlterGuru
    Data registrazione
    29-12-2015
    Messaggi
    1,954

    Predefinito

    Con quel codice apri una nuova connessione per ogni singola interrogazione o preparazione di uno statement, su ogni connessione esegui una singola operazione quindi hai il massimo dell'inefficienza!

    Una miglioria che puoi applicare fin da subito consiste nell'aprire una singola connessione per tutto il ciclo di vita della classe CONF:
    Codice PHP:
    class CONF{
    // Esiste un'unica connessione (statica), non ne vengono aperte in continuazione di nuove
    private static $pdo = null;


    public static function
    PDO() {
    // Se la connessione non è stata precedentemente aperta prima, la apre ora (approccio lazy)
    // In ogni caso ne viene aperta solo una per tutto il ciclo di vita della classe CONF
    if (is_null(self::$pdo)) {
    try {
    self::$pdo = new PDO("mysql:host=" . HOST . ";dbname=" . DBNAME, DBUSER, DBPASSW);
    } catch (
    PDOException $e) {
    return
    "Connection failed: " . $e->getMessage();
    }
    }

    // Restituisce l'oggetto PDO pronto per l'uso
    return self::$pdo;
    }
    }
    Per altri dettagli guarda il Singleton Design Pattern.

    qual'è il massimo di connessioni che Altervista ti permette di fare?
    I server MySQL usano un valore attorno a 150 come numero massimo di connessioni, ma in ambienti di hosting condivisi è molto frequente avere valori minori. In ogni caso è un parametro di sistema max_connections.

  5. #5
    Guest

    Predefinito

    Ti ringrazio infinitamente per queste dritte! Vedrò di sistemare le mie falle!

Regole di scrittura

  • Non puoi creare nuove discussioni
  • Non puoi rispondere ai messaggi
  • Non puoi inserire allegati.
  • Non puoi modificare i tuoi messaggi
  •