NYCPHP Meetup

NYPHP.org

[nycphp-talk] aggregate views on serialized session data WAS: session size important?

Dan Cech dcech at phpwerx.net
Fri Apr 22 15:22:41 EDT 2005


Mitch Pirtle wrote:
> On 4/22/05, csnyder <chsnyder at gmail.com> wrote:
>>Oh, and, pay special attention to your garbage collection routines - a
>>session table with 800,000 stale records is not a pretty sight.
> 
> I never did get ADOdb's session_expiration stuff working to clean out
> those records, and was forced to find another solution. I ended up
> omitting reference to that altogether for an article on using ADOdb
> and got in the John Lim Doghouse for it too (gasp!)

Yeah, never having actually used ADOdb's session handlers in the real 
world (because I had my own already) I wasn't aware of this.  The gc 
handler does seem unnecessarily complex.  I'm also not a fan of 
pre-computing expiry times, I prefer to set an activity time and compute 
the expiry time as needed to keep things consistent if you change the 
timeout value.

Here is the handler I used, which assumes you set a column called 
'active' to the current gmtime() each time you update the session data 
(The optimize table stuff is obviously MySQL specific).

<?php

define('SESSION_TABLE','sessions');

/*! function
  internal session management function
  !*/
function _sess_gc ($gc_maxlifetime = NULL)
{
   $db = ''; //db connection

   if (!isset($gc_maxlifetime)) {
     $gc_maxlifetime = ini_get('session.gc_maxlifetime');
   }

   $gc_sql = 'DELETE FROM '. SESSION_TABLE .' WHERE active < '. (gmtime 
() - $gc_maxlifetime);
   $result = $db->Execute($gc_sql);

   if (!is_object($result)) {
     trigger_error ('_sess_gc (): Failed to DELETE old sessions.', 
E_USER_WARNING);
     return FALSE;
   }

   $opt_sql = 'OPTIMIZE TABLE '. SESSION_TABLE;
   $result = $db->Execute($opt_sql);

   if (!is_object($result)) {
     trigger_error ('_sess_gc (): Failed to OPTIMIZE session table.', 
E_USER_WARNING);
     return FALSE;
   }

   /*
   // uncomment to test if garbage collection gets called properly
   if ($fp = fopen ('/tmp/gc.txt','ab')) {
     fwrite($fp,gmtime() .' - '. $gc_sql ."\n");
     fclose($fp);
   }
   */

   // trigger_error ('_sess_gc (): Session Garbage Collection 
successful.', E_USER_NOTICE);
   return TRUE;
}

> So, I've taken two different approaches to get the "There are X people
> online" view:
> 
> 1) store the online status as a boolean in the session table, and just
> get counts
> 2) store the summary count data in memory, and update for each login/logout
> 
> I am unconvinced that one is better over the other, what does everyone
> else think? #2 is certainly the fastest until you need multiple
> servers, but #1 means you gotta count for every aggregate.

As for counting users, in MySQL at least, if you put an index on the 
'active' field then you can use something like:

'SELECT COUNT(*) FROM '. SESSION_TABLE .' WHERE active >= '. (gmtime()-300);

To get a count of all users active in the last 5 minutes, and (again at 
least for MySQL) it should be fairly fast because it can be computed 
using only the index.

You could maybe use a hybrid approach where you maintain a value (either 
in the db or in some other cache) of the current count and increment it 
on login/logoff, but add a function to the session gc handler to perform 
the count and keep it in sync.  I guess it really depends on how 
accurate you want the count to be.

Dan



More information about the talk mailing list