Every PHP request opens its own database connection, so a hundred concurrent requests is a hundred connections — and there is no pool because there is no process to hold one.
; persistent connections: reused per php-fpm WORKER, not per request
mysql.allow_persistent = 1
; PDO::ATTR_PERSISTENT => true
; the trap: a persistent connection keeps session state —
; temporary tables, prepared statements, transaction status,
; SET variables — across unrelated requests.
; the actual answer at scale: ProxySQL or MySQL Router in front.
Persistent connections are per worker rather than per request, which caps connections at the pool size and is genuinely useful — and the retained session state is a real hazard that has produced very confusing bugs, particularly an uncommitted transaction inherited by the next request. A proxy in front is what other runtimes get from a pool and is the arrangement that scales. Raising max_connections until it works is the third option and is how a server runs out of memory.