In my watchdog on a D5 install, I regularly get around 10 error messages which are followed by the 'Number of sessions deleted: XXXXXX' message. Those error message look like:
Lock wait timeout exceeded; try restarting transaction query: UPDATE sessions SET uid = 0, cache = 0, hostname = 'xxx.xxx.xxx.xxx', session = '...', timestamp = 1251277008 WHERE sid = '67d0a2fa61c072d2331a4d7ac5cb1132' in /var/www/drupal/includes/database.mysql.inc on line 174.
My expire sessions settings are set as
Interval: 6 hours
Age: 1 week
Session types: anonymous (only)
More info:
Cron is run every 15 min
And the average of sessions removed every 6 hours is 50.000
The sessions table uses InnoDb
I wonder how I can avoid the locks.
Comments
Comment #1
kbahey commentedThe module does not do an explicit LOCK TABLE. All it does is:
However, you may have set a certain variable, such as innodb_lock_wait_timeout too low, or the default of your distro is too low. It is set to 50 on the distro I use (Ubuntu). If the operation of deleting takes longer than 50 seconds, then you may get those errors.
SHOW INNODB STATUS, SHOW VARIABLES and, SHOW PROCESSLIST may be of help when cron is running. You need to catch it in the action.
Comment #2
toemaz commentedHi Khalid, thanks for the fast reply.
The variable innodb_lock_wait_timeout is set to 50. I'll try to run the SHOW INNODB STATUS when it's running as well as the SHOW PROCESS LIST.
Comment #3
xurizaemonIncreasing the timeout on your LOCK is not a fix IMO, because people visiting the site during that period will just see a hang.
As I understand it, all rows in the table will be locked for SELECT as long as the DELETE query is running. The solution is to reduce the time your DB server spends in DELETE.
The simple but more brutal approach is to simply do
TRUNCATE sessionsin your DB. This will remove all existing sessions, and log out all currently active users. If the issue is that your sessions table got too fat before you installed Session Expire module, then this may well bring your sessions table to a manageable level, and after that Session Expire will have an easier job keeping things in order.If that's not an option, a more complex approach which allows you to avoid disturbing "current" sessions is by executing a looped statement. You could time queries like
DELETE FROM sessions WHERE timestamp < UNIX_TIMESTAMP()-1*24*60*60 LIMIT xand decide on what an acceptable delay is, then repeat the query for that value ofxuntil you've flushed the table sufficiently.(1*24*60*60 in the query above represents the number of seconds in a day; to keep sessions up to a week old, use 7*24*60*60, etc.)
If your question is resolved, please take a moment to mark this issue fixed.
Comment #4
toemaz commentedHi xurizaemon,
Thanks a lot for the extensive info. Before I installed the sessions expire module, the sessions table went up to 2M records. That became a little to fat indeed.
I indeed created a custom solution but haven't spend the time yet to give it a good review whether it has been solved. It almost exactly what you proposes with the LIMIT x. I'll put this issue on fixed for the time being but will come back to it to explain my solution.
Thanks
Comment #5
xurizaemonThere might be a feature request here, then: when enabling Session Expire, check and see the size of the sessions table. If it's "large" (eg, if
select count(*) from sessions where sessions.timestamp < unix_timestamp()-7*24*60*60 ;takes more than a second or two to execute) then warn the person installing the module to do a manual cleanup.Alternatively, we could do something like this in expiry phase:
Comment #6
xurizaemon#263130: Big session tables can crash SQL server records similar issues experienced by other sites.
Comment #8
xurizaemon#934876: Avoid long {sessions} table locks is the feature request which grew from this issue.