skip to content

Persistent Connections

PDO::ATTR_PERSISTENT and mysqli's p: prefix keep one connection open per worker process instead of pooling it. Interviewers probe the max_connections math and state left on a reused link.

part ofPHPoverview, primer and where to startread it →
on this pageshow

explore

questions

4

In PHP, how do you request a persistent database connection with PDO and with mysqli, and what does 'persistent' mean there?

level: juniorimportance: should knowfreq 42%

answer

  1. survives the end of the script
  2. kept by the worker process
  3. constructor options only
  4. PDO::ATTR_PERSISTENT => true
  5. p: prefix on the mysqli host

basics

~20 s

Pass PDO::ATTR_PERSISTENT => true in PDO's constructor options, or prefix the mysqli host with p:. The connection then stays open in that worker process after the request and is reused by its next request with the same credentials.

solid answer

~40 s

With PDO I pass `PDO::ATTR_PERSISTENT => true` in the **constructor's** options array; setting it later with `setAttribute()` has no effect on persistence. With mysqli I prefix the host, `new mysqli('p:db', ...)`. Persistent means the connection is not closed when the script ends: it stays in the process that served the request, and the next script in that same process asking for an identical connection — same DSN, user and password for PDO — gets it back instead of reconnecting. It only helps under PHP-FPM or an Apache module, where processes serve many requests; in CLI scripts each run is a new process. It saves connection setup time and adds no other capability.

code

php · 11 lines
php
<?php
declare(strict_types=1);

// PDO: persistent only when set in the constructor options.
$pdo = new PDO('mysql:host=db;dbname=news;charset=utf8mb4', $user, $pass, [
    PDO::ATTR_PERSISTENT => true,
]);
var_dump($pdo->getAttribute(PDO::ATTR_PERSISTENT)); // bool(true)

// mysqli: persistent through the p: host prefix.
$db = new mysqli('p:db', $user, $pass, 'news');

go deeper

for a junior

Recall the two spellings: PDO::ATTR_PERSISTENT in the constructor options and the p: host prefix in mysqli.

for a middle

Explain what the lookup key is made of and why persistence only matters under SAPIs whose processes serve many requests.

for a senior

Know the side effects before switching it on: connection counts and state left over from earlier requests.

for a principal

Treat persistence as a latency trade-off to measure, not a default, and weigh it against fixing slow connection setup directly.

## What "persistent" means in PHP A normal database connection opened by a PHP script is closed when the script ends. A **persistent connection** is not: PHP keeps it open in the **process** that served the request and hands it back to a later script in that same process when it asks for an identical connection. The manual defines "identical" as the same host with the same username and password, and each extension builds its lookup key from its own connection parameters. Persistence saves one thing: the time to open a connection — the network round-trips, the authentication handshake and, with TLS, the encryption setup. It adds no new capability. The manual states it directly: persistent connections do not provide any functionality that was not possible with non-persistent connections. ## Asking for one with PDO Pass `PDO::ATTR_PERSISTENT => true` in the **options array of the constructor**: ```php $pdo = new PDO('mysql:host=db;dbname=news;charset=utf8mb4', $user, $pass, [ PDO::ATTR_PERSISTENT => true, ]); ``` - It must be in the constructor options. Setting it later with `setAttribute()` does not make the connection persistent; the manual says the driver will not use persistent connections in that case. - PDO's lookup key is the DSN, the username and the password. A different DSN string — even the same server written another way — means a different persistent connection. - The option may also be a non-numeric string, which becomes part of the key. That lets one process keep separate persistent connections for settings that must not be mixed. - `$pdo->getAttribute(PDO::ATTR_PERSISTENT)` reports whether the handle you got is persistent. ## Asking for one with mysqli mysqli has no separate function or option. You prefix the host with **`p:`**: ```php $db = new mysqli('p:db', $user, $pass, 'news'); ``` - mysqli's key covers host, socket, port, username, database and password. - The `php.ini` directive `mysqli.allow_persistent` (default `On`) can disable persistence; a `p:` connect then falls back to a normal connection with the warning "Persistent connections are disabled. Downgrading to normal". - `mysqli.max_persistent` (default `-1`, no limit) caps persistent links per process. ## When it actually persists | How PHP runs | Does the connection survive the request? | |---|---| | PHP-FPM | yes, in that worker process, for its next requests | | Apache with PHP as a module | yes, in that Apache child process | | CGI | no — the interpreter exits after each request | | CLI scripts and cron jobs | no benefit — each run is a new process that exits | The manual suggests checking the Server API (`PHP_SAPI` or `phpinfo()`): "FPM/FastCGI" and "Apache 2 Handler" keep connections across requests; other values do not. ## What you do not get 1. You cannot ask for a **specific** earlier connection; the next request may land on another worker with its own connection. 2. You cannot keep a transaction open across requests, or start a query in one request and read it in the next. 3. You do not get a shared pool; each process holds its own. 4. You still get a working connection if the old one died: before reuse, PDO's MySQL driver pings the server and reconnects when the ping fails. ## Before switching it on Persistence is a trade-off, and the manual itself says it should not be enabled without careful consideration. Check three things first: - **Is connection setup actually slow?** Measure it. A database on the same network, without reverse DNS lookups on login, often connects fast enough that persistence saves little. - **Can the database hold one connection per worker?** Every worker that has connected keeps its link while idle, so the database's connection limit must exceed the total worker count. - **Does the code leave session state behind?** Settings, temporary tables and locks from one request can reach the next request on that worker. If any answer is unclear, start with ordinary connections and revisit persistence once measurements show connection setup matters. ## The short answer in an interview "Persistent" in PHP means *kept open by the worker process between requests*, requested with `PDO::ATTR_PERSISTENT` in the constructor or a `p:` host prefix in mysqli, and useful only under a SAPI whose processes serve many requests.

  • What happens if you call $pdo->setAttribute(PDO::ATTR_PERSISTENT, true) after connecting?
    The connection is already open as a normal one, and the manual states the driver will not use persistent connections when the attribute is set after instantiation. Persistence is decided while the constructor looks up or creates the handle, so the option has to be in the constructor's options array.
  • Is there any point in persistent connections for a nightly cron job written in PHP?
    No. A CLI run is its own process, and the process exits when the script ends, taking the connection with it. Nothing survives for a later run to reuse. Persistence pays off only where one process serves many requests, such as PHP-FPM workers.

saying these in an interview costs you the question

  • Believing a persistent connection is shared by every request on the server.
  • Setting PDO::ATTR_PERSISTENT with setAttribute() after the constructor.
  • Expecting persistent connections to keep a transaction open across requests.
  • Thinking persistence helps short CLI scripts and cron jobs.
  • Looking for a separate mysqli function to open persistent links.
open as a page

Why is a PHP persistent database connection under PHP-FPM not a connection pool, and how many connections does each worker hold?

level: middleimportance: should knowfreq 40%

basics

~20 s

Each PHP-FPM worker serves one request at a time and keeps its own persistent connection per distinct key, so nothing is shared or borrowed. It is a per-process cache: one connection per worker per DSN and credentials, idle or busy.

open as a page

In PHP, what state can a reused PDO persistent connection carry over from an earlier request, and how does mysqli's p: prefix handle it differently?

level: seniorimportance: should knowfreq 28%

basics

~20 s

A reused PDO persistent connection keeps session state from the earlier request: SET variables, temporary tables, the selected database and locks. mysqli's p: links run a change-user cleanup on reuse that rolls back, drops temp tables, unlocks and resets session variables.

open as a page

After a news site raised its PHP-FPM worker count, MySQL began refusing logins with 'Too many connections'; how do PDO persistent connections cause this, and how do you fix it?

level: seniorimportance: should knowfreq 35%

basics

~20 s

Each FPM worker keeps its own persistent connection per DSN and user, even while idle, so connections grow to servers × workers × keys and overran MySQL's limit. Resize workers, disable persistence or add a pooling proxy.

open as a page