zendframework / zf1

This project reached its end-of-life on 2016-09-28. Contains conversion of ZF1 subversion repo to git, from version 15234 forward, and only containing master and release-1.12 branches and 1.12 tags.
https://framework.zend.com/blog/2016-06-28-zf1-eol.html
BSD 3-Clause "New" or "Revised" License
357 stars 800 forks source link

Writing session to table on request close fails over multiple servers #41

Open zfbot opened 11 years ago

zfbot commented 11 years ago

Jira Information

Original Issue:ZF-12485
Issue Type:Bug
Reporter:Cosmin Budrica
Created:12/07/12
Assignee:Ralph Schindler
Components:Zend_Session

Description

Scenario: Same user, same browser, sends multiple ajax requests to the server at the same time. Requests are being balanced by a load balancer, and sent to multiple servers, with the same database as storage.

Error: "PHP Fatal Error: Exception thrown without a stack frame in Unknown on line 0" - very helpful of course

Issue: The code that finds the session in the database and updates or inserts it is not doing this in one go.

$rows = call_user_func_array(array(&$this, 'find'), $this->_getPrimary($id));

if (count($rows)) {
   $data[$this->_lifetimeColumn] = $this->_getLifetime($rows->current());

   if ($this->update($data, $this->_getPrimary($id, self::PRIMARY_TYPE_WHERECLAUSE))) {
       $return = true;
   }  
} else {
   $data[$this->_lifetimeColumn] = $this->_lifetime;

   if ($this->insert(array_merge($this->_getPrimary($id, self::PRIMARY_TYPE_ASSOC), $data))) {
       $return = true;
   }
}

Problem is, that anywhere between the find and insert, other servers might have already inserted that session, resulting this particular request to fail, with a real error message of: Duplicate entry on primary key "$session id".

My solution for the time being was to wrap this up in a database transaction, but all that code there should translate into something like:

$rows = $dbAdapter->findOrCreate($this->_getPrimary($id), $data);

and let the adapter(mysql, postgres, oracle, whatever) decide what the best method of inserting or updating is. For example, on mysql, most probably an INSERT () ON DUPLICATE KEY UPDATE would be the best solution.

PS: this is going on in Zend Framework 2 also.

zfbot commented 11 years ago

(Originally posted by: froschdesign on 12/07/12)

Please also add your report in the bugtracker at Github|https://github.com/zendframework/zf2/issues.

zfbot commented 11 years ago

This issue was ported from the ZF2 Jira Issue Tracker at http://framework.zend.com/issues/browse/ZF-12485

Known GitHub users mentioned in the original message or comment: @froschdesign