xPDO Persistent Connection Default Change in MODX 3.0 Leads to Connection Pool Exhaustion
0 reputation · 26 Oct 2020, 18:20 UTC
0 reputation · 26 Oct 2020, 18:20 UTC
The goal is to decide whether MODX should expose administrator‑configurable xPDO connection pool parameters, such as an idle timeout or maximum pool size, to mitigate intermittent 'Too many connections' errors observed under high traffic. In MODX Revolution 3.x the default connection mode switched to persistent PDO connections when the driver supports them, a change documented only in the upgrade notes. This shift removes the per‑request fresh connection model of MODX 2.x and leaves connection lifecycle control entirely to the PHP PDO extension and the MySQL server, which provides no built‑in idle timeout or recycling mechanism for persistent connections.
Should MODX add a system setting for an xPDO persistent connection idle timeout that respects MySQL's wait_timeout? Would exposing a configurable maximum pool size via a new setting improve stability without breaking existing custom scripts that assume a fresh PDO instance per request? Is reliance on MySQL wait_timeout and manual pool flushing sufficient, or does MODX need native connection pool management?
33275 reputation · 26 Oct 2020, 23:29 UTC
Yes, MODX should expose administrator‑configurable xPDO persistent connection idle timeout and maximum pool size via system settings.
In MODX 3.x the default connection mode switched to persistent PDO connections when the driver supports them. Persistent connections are kept open after each request and are reused by the same PHP‑FPM worker or Apache process. Because PHP’s PDO extension does not provide an idle timeout or automatic recycling, these connections remain idle until MySQL closes them based on its wait_timeout variable. Under high traffic the number of concurrent PHP‑FPM workers can exceed MySQL’s max_connections, causing the pool to fill with idle connections and eventually trigger “Too many connections” errors.
max_connections, connection exhaustion occurs.max_connections and the PHP‑FPM pm.max_children (or Apache MaxRequestWorkers) values.pm.max_children (or equivalent) is close to or greater than max_connections, proceed to add configurable limits.xpdo_persistent_idle_timeout – integer seconds, passed to PDO via ATTR_PERSISTENT handling or used to trigger a custom cleanup script that calls PDO::setAttribute(PDO::ATTR_TIMEOUT, ...) or executes KILL on idle connections.xpdo_persistent_max_pool_size – integer, limits the number of persistent connections each PHP worker may hold (implemented by wrapping xPDO’s connection factory to close excess connections).wait_timeout (or a fraction thereof) and max pool size = max_connections divided by expected worker count.SHOW PROCESSLIST for a reduction in Sleep connections and verify that “Too many connections” errors disappear.To confirm whether the proposed settings are necessary, please provide the current values of MySQL’s max_connections and the PHP‑FPM pm.max_children (or Apache equivalent). If those numbers show a comfortable margin, the change may be less urgent.
Use comments to ask for clarification. Post a solution as an answer.
33,275 reputation · 26 Oct 2020, 20:03 UTC
While adding system settings for pool management is a logical step, it is important to clarify that xPDO's persistent connections are tied to the lifecycle of the PHP process. In a PHP-FPM environment, each child process maintains its own persistent connection to the database.
This means that the effective "pool size" is not a single global value managed by MODX, but is instead the sum of all active PHP-FPM workers. To verify the current pressure on the database, administrators should compare the following values:
SHOW VARIABLES LIKE 'max_connections';pm.max_children setting in the pool configuration.If pm.max_children exceeds max_connections, exhaustion is inevitable regardless of idle timeouts, as the database cannot accommodate the maximum possible concurrency of the web server.