php / php/php-src

ext/mysqli: mysqli double increments num_active_persistent when using real_connect

Offen
#22,631 5 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bug Extension: mysqli Status: Needs Triage
Vorherrschende Sprache
C
Sterne
40.4k
Forks
8.2k
Ø Merge
2 T. 13 Std.
Gemergte PRs (30 T.)
96

Beschreibung

Description

The following code:

<?php

$use_real_connect = true;

$host = "p:localhost";
$user = "root";
$password = "password";

for ($i = 0; $i < 100; $i++)
{
  if ($use_real_connect)
  {
    $mysql = mysqli_init();
    mysqli_real_connect($mysql, $host, $user, $password);
  }
  else
  {
    $mysql = mysqli_connect($host, $user, $password);
  }
  mysqli_close($mysql);
}

$stats = mysqli_get_links_stats();
var_dump($stats);

Resulted in this output:

array(3) {
  ["total"]=>
  int(0)
  ["active_plinks"]=>
  int(99)
  ["cached_plinks"]=>
  int(1)
}

But I expected this output instead:

array(3) {
  ["total"]=>
  int(0)
  ["active_plinks"]=>
  int(0)
  ["cached_plinks"]=>
  int(1)
}

The code gives the correct output if you turn off the $use_real_connect flag.

This is caused by the persistent branch of mysqli_common_connect incrementing num_inactive_persistent (mysqli_nonapi.c:179 in tag php-8.5.8) when a persistent connection is reused based on the connection hash, then jumping to the end: label, and incrementing it again under this condition:

// mysqli_nonapi.c:296
if (persistent && (new_connection || is_real_connect)) {
    MyG(num_active_persistent)++;
}

Because mysql_close has already been called on the persisted connection, we get a total increase in active persistent connections by 1.

I'm not entirely sure why || is_real_connect is needed in that check, it looks to me like new_connection still covers the persistent case.

EDIT: The consequence of this issue is that if you make a persistent connection a ton of times (say in a long-running php-fpm process), and then make a different connection that doesn't yet exist in the connections hash table, you will always fail with the error Too many open persistent links with a massively huge number of active persistent connections. Note that this does not actually leak connections to the server, you still are capped properly by at most mysqli.max_persistent.

PHP Version
PHP 8.5.8 (cli) (built: Jul  6 2026 16:48:54) (NTS)
Copyright (c) The PHP Group
Built by https://github.com/docker-library/php
Zend Engine v4.5.8, Copyright (c) Zend Technologies
    with Zend OPcache v8.5.8, Copyright (c), by Zend Technologies
Operating System

Debian 13.5

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne mit ext/mysqli/mysqli_nonapi.c, insbesondere mit mysqli_common_connect und der Zählung der persistenten Verbindungen rund um die genannten Zeilen. Führe den bereitgestellten Reproducer mit aktiviertem real_connect aus und überprüfe anschließend, dass wiederholte Wiederverwendung active_plinks bei 0 und cached_plinks bei 1 belässt, ohne das Verhalten von non-real_connect zu ändern.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
c, php
Bereich
databases
Issue-Typ
Bug
Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Aktivitätsstatus
Ruhig
Klarheit
Klar beschrieben
Anfängerfreundlichkeit
68/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.