Welcome Guest, Not a member yet? Register   Sign In
Locking session with extra table (Galera cluster)
#1

(This post was last modified: 08-03-2015, 05:28 AM by Jammyman.)

Galera cluster doesn't support locking tables (MySQL, MariaDB), so the new Session library doesn't work with it (random segfaults).

File driver is not an option with load balancer and at the time being there's no support for Redis and Memcahed either so I need figure out other way lock the session.

I've been testing locking with extra table and it seems to work reasonably well even under tons of ajax calls (although can be little slow if lot's of stuff waiting).

Because there's no "real lock", sometimes one process can create lock while other is doing it too, resulting Duplicate Entry -error in other query.  I can detect the error in the code below but I'm not too happy about script making query errors to my logs etc. I tried transactions for this too but while it worked, I got same error to my logs.

So this seems to work, but any ideas how to improve it? Or other ides how to do it?

Table:
PHP Code:
CREATE TABLE `ci_sessions_lock` (
 
 `idvarchar(40NOT NULL DEFAULT '',
 
 `timestampint(10unsigned NOT NULL,
 
 PRIMARY KEY (`id`)
ENGINE=InnoDB DEFAULT CHARSET=utf8

Get lock:
PHP Code:
if ($this->_platform === 'mysql')
{
   $arg $session_id . ($this->_config['match_ip'] ? '_' $this->ip_address '');

   $attempt 0;
   $expired_lock_time time() - 300;

   do
   
 
       
// Check if we have locks
       $this->_db
           
->select('id,timestamp')
           ->from('ci_sessions_lock')
           ->where('id'$arg);

       $result $this->_db->get()->row(0);

       // If lock is too old, let's delete it
       if ($result && $result->timestamp $expired_lock_time)
       {
           $this->_db->delete('ci_sessions_lock', array('id' => $arg));
           $result false;
       }

       // If lock is found, we need to wait until it's deleted
       if ($result)
         
           sleep
(1);
           continue;
       }

 
      // Let's create the lock
       $timestamp time() + 300;
       $query $this->_db->query('INSERT INTO ci_sessions_lock (id, timestamp) VALUES (\'' $arg '\', ' $timestamp ')');

       // Most likely if we have error at this point, it's because duplicate key exist
       // So let's wait more
       if ( ! $query)
       {
           sleep(1);
           continue;
       }

       $this->_lock $arg;
       break;
   }
   while (++ $attempt 30);

   if ($attempt === 30)
   {
       log_message('error''Session: Unable to obtain lock for ' $arg ' after 30 attempts, aborting.');
       return false;
   }

   return true;


Release lock:
PHP Code:
if ($this->_platform === 'mysql')
  
    $this
->_db->delete('ci_sessions_lock', array('id' => $this->_lock));
 
   $this->_lock false;

Reply




Theme © iAndrew 2016 - Forum software by © MyBB