After we switched our project from PHP5 to PHP7, there were problems during SELECT (deadlocks) and DELETE (timeouts) commands on the session table. We didn’t take a look at it for a long time, but there were more than 20 Million (!) entries since Octoboer 2020. Obviously, the deletion which took too long ruined the select statement.
We switched the production system back to PHP5, where it seems that the deletion is not happening here. Currently, the oldest entry on the production database is from 2 days ago after our cleanup. Our test system (running on PHP7, with its own database) seems to clean up anything older than 10 hours (hence the lifetime-value of 36000 seconds, as seen in the session table).
Since there is no cronjob or anything similar that’s set to clean up, the Zend Framework seems to clean things up by itself. But we cannot see WHEN this is happening, so we would like to understand the “magic” behind this.
It’s Zend Framework 1.12 (I know, very old, but deciding to switch the framework first was not in my hands, but it’s in the pipeline).
Here’s the exception of the deadlock itself:
PHP Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 20003 Adaptive Server connection timed out [20003] (severity 6) [DELETE FROM "Session" WHERE ("modified" + "lifetime" < 1644330881)] in /var/www/[...]/library/Zend/Db/Statement/Pdo.php:228 Stack trace: #0 /var/www/[…]/library/Zend/Db/Statement/Pdo.php(228): PDOStatement->execute(Array) #1 /var/www/[…]/library/Zend/Db/Statement.php(303): Zend_Db_Statement_Pdo->_execute(Array) #2 /var/www/[…]/library/Zend/Db/Adapter/Abstract.php(480): Zend_Db_Statement->execute(Array) #3 /var/www/[…]/library/Zend/Db/Adapter/Pdo/Abstract.php(238): Zend_Db_Adapter_Abstract->query('DELETE FROM "Se...', Array) #4 /var/www/[…]/library/Zend/Db/Adapter/Abstract.php(664): Zend_Db_Adapter_Pdo_Abstract->query('DELETE FROM "Se...') #5 /var/www/[…]/library/Zend/Db/Table/Abst in /var/www/[…]/library/Zend/Db/Statement/Pdo.php on line 235
Edit:
There’s a class named
Zend_Session_SaveHandler_DbTable
with a method called gc
. But it’s still not obvious when it’s called.
Advertisement
Answer
The session handler’s gc() method is called by PHP. See how the handler is registered using the PHP’s native function here: https://github.com/diablomedia/zf1-session/blob/11c4bf70b8f87a3f30883fd85f2b9fe4b8afd250/src/Zend/Session.php#L265-L272
So it seems that the settings of session garbage collection in your php.ini (https://www.php.net/manual/en/session.configuration.php#ini.session.gc-probability and others) are different for the different PHP versions. Check them and you should see the difference.