Page 1 sur 1

mysql_pconnect et mysql_close

Posté : 09 mai 2008, 15:11
par Louisss
Bonjour.

Je suis en train de m'intéresser de près aux connexions persistantes, et dans la documentation PHP, il est répété de nombreuses fois qu'une connexion persistante (donc ouverte avec mysql_pconnect) NE PEUT PAS ETRE FERMEE AVEC MYSQL_CLOSE().

Or, je me suis fait un petit script pour tester la chose et j'en arrive à la conclusion inverse (PHP 5.2.3 et MySQL 5.0.41). Voici le code :

Code : Tout sélectionner

mysql_pconnect("localhost:3306", "root", "root"); mysql_select_db("test"); $req = "SELECT * FROM toto"; $res = mysql_query($req); echo "Nombre d'enregistrements trouvés : ".mysql_numrows($res); mysql_close(); $req = "SELECT * FROM toto"; $res = mysql_query($req); echo "Nombre d'enregistrements trouvés : ".mysql_numrows($res);
Et voici le résultat à l'exécution sur mon serveur local (MAMP) :

Code : Tout sélectionner

Nombre d'enregistrements trouvés : 7 Warning: mysql_numrows(): supplied argument is not a valid MySQL result resource in /Users/louisbelval/Documents/MAMP/Exemples/Bases de donnees/Connexion persistante.php on line 21 Nombre d'enregistrements trouvés :
Autrement dit, avant le mysql_close(), la requête est bien exécutée, après le mysql_close(), elle ne l'est plus. Ca veut pas dire que la connexion a été fermée par le mysql_close(), ça ? Et pourtant, c'est une connexion persistante ouverte avec mysql_pconnect().

Alors l'erreur est où ? Dans la doc, ou dans mon code ? En tout cas, la documentation ne signale visiblement pas que mysql_close() puisse fermer dans certains cas une connexion persistante.

J'en profite pour poser une autre question, du coup : si une connexion persistante est sensée ne pas pouvoir être fermée automatiquement à la fin d'un script ou par mysql_close(), comment on la ferme alors ?

Merci d'avance pour vos réponses

Posté : 09 mai 2008, 16:27
par zeus
Ton soucis m'a interpellé et j'ai testé de mon côté.

Il s'avère que si tu fait un mysql_close(), mysql_query() ne sélectionne plus implicitement la connexion à utiliser, et c'est la raison pour laquelle ta seconde requête échoue.

Par contre, si tu donnes explicitement la ressource mysql, la requête fonctionne.
Exemple (note bien où est-ce que j'utilise $o_db):
$o_db = mysql_pconnect('127.0.0.1', 'root', '');
mysql_select_db('dotclear');

$req2 = "SELECT * FROM dc_categorie";
$res2 = mysql_query($req2, $o_db);
echo "Nombre d'enregistrements trouvés : ".mysql_num_rows($res);

mysql_close();

$req2 = "SELECT * FROM toto";
$res2 = mysql_query($req, $o_db);
echo "Nombre d'enregistrements trouvés : ".mysql_num_rows($res2); 
Affiche bien
Nombre d'enregistrements trouvés : 2
Nombre d'enregistrements trouvés : 2
La réponse à la seconde question est identique : pour fermer une connexion persistance, il faut utiliser mysql_close(), mais sur une connexion explicite
Exemple (regarde bien le $o_db dans le mysql_close()) :
$o_db = mysql_pconnect('127.0.0.1', 'root', '');
mysql_select_db('dotclear');

$req = "SELECT * FROM dc_categorie";
$res = mysql_query($req, $o_db);
echo "Nombre d'enregistrements trouvés : ".mysql_num_rows($res);

mysql_close($o_db);

$req2 = "SELECT * FROM toto";
$res2 = mysql_query($req, $o_db);
echo "Nombre d'enregistrements trouvés : ".mysql_num_rows($res2); 
Et ce code là echoue sur la seconde requête en affichant un message d'erreur.

Posté : 09 mai 2008, 18:12
par x0s
Du coup, ça m'a aussi intrigué et en effet, si on regarde dans les sources de PHP 5, on peut voir les choses suivante :
PHP_FUNCTION(mysql_close)
{
	zval **mysql_link=NULL;
	int id;
	php_mysql_conn *mysql;

	switch (ZEND_NUM_ARGS()) {
		case 0:
			id = MySG(default_link);
			break;
		case 1: // Ici on pointe une ressource spécifique[/b]
			if (zend_get_parameters_ex(1, &mysql_link)==FAILURE) {
				RETURN_FALSE;
			}
			id = -1;
			break;
		default:
			WRONG_PARAM_COUNT;
			break;
	}
	
	ZEND_FETCH_RESOURCE2(mysql, php_mysql_conn *, mysql_link, id, "MySQL-Link", le_link, le_plink);

	if (id==-1) { /* explicit resource number */
		PHPMY_UNBUFFERED_QUERY_CHECK();
		zend_list_delete(Z_RESVAL_PP(mysql_link)); // Et là on force la suppression de la ressource spécifiée en argument
	}

	if (id!=-1 
		|| (mysql_link && Z_RESVAL_PP(mysql_link)==MySG(default_link))) {
		PHPMY_UNBUFFERED_QUERY_CHECK();
		zend_list_delete(MySG(default_link));
		MySG(default_link) = -1;
	}

	RETURN_TRUE;
}
  • Lors de l'appel de mysql_close() : Tout les link de connexion par défaut sont supprimés (entrainant automatiquement et uniquement la fermeture des connections non persistantes)
    $o_db = mysql_pconnect('127.0.0.1', 'root', '');
    mysql_select_db('dotclear');
    
    $req2 = "SELECT * FROM dc_categorie";
    $res2 = mysql_query($req2, $o_db);
    echo "Nombre d'enregistrements trouvés : ".mysql_num_rows($res);
    
    mysql_close(); // Suppression de tout les links par défaut ou non persistants ($o_db est donc évité)
    
    $req2 = "SELECT * FROM toto";
    $res2 = mysql_query($req, $o_db);
    echo "Nombre d'enregistrements trouvés : ".mysql_num_rows($res2);
    
  • Lors de l'appel de mysql_close(resource_id) : Le link de connexion spécifique à resource_id est supprimé (même remarque quand à la fermeture réelle de la connexion correspondante).
    $o_db = mysql_pconnect('127.0.0.1', 'root', '');
    mysql_select_db('dotclear');
    
    $req = "SELECT * FROM dc_categorie";
    $res = mysql_query($req, $o_db);
    echo "Nombre d'enregistrements trouvés : ".mysql_num_rows($res);
    
    mysql_close($o_db); // ici on supprime directement le link de la connexion persistante, ce qui fait que les fonctions suivantes échouent car elles ne pointe plus sur de ressource valide
    
    $req2 = "SELECT * FROM toto";
    $res2 = mysql_query($req, $o_db);
    echo "Nombre d'enregistrements trouvés : ".mysql_num_rows($res2);
    
Pour conclure sans entrer dans les détails, mysql_close amorce une phase de suppression des links de connections (BDD) et entraine une phase de fermeture des connections non persistantes.

Reste à voir dans le détail ce qui se passe vraiment...

Posté : 10 mai 2008, 13:38
par Louisss
Super, merci beaucoup.

Mais du coup, peut-on en conclure qu'il n'y a pas de fermeture automatique des connexions persistantes ?
J'avais pourtant cru comprendre qu'une connexion persistante était fermée automatiquement si elle n'était pas utilisée pendant mysql.connect_timeout secondes.

C'est vrai, ça ?

Posté : 11 mai 2008, 21:58
par x0s
hum...

Regarde plutôt du coté d'interactive_timeout :
http://dev.mysql.com/doc/refman/5.0/fr/ ... ables.html

Généralement, wait_timeout prend la valeur d'interactive_timeout