|  | Posted by Marek Kilimajer on 03/16/05 19:59 
Josh Whiting wrote:> I've been trying to switch to MySQL-based session storage instead of the
 > native PHP session storage.  In doing so, I've run into a lot of code on
 > the web that exhibits a serious flaw regarding concurrent requests from
 > the same client. All the code I've seen has glossed over the need to
 > lock the session for the duration of the request, e.g. not allow
 > concurrent requests to use it until it has finished.  PHP's native
 > session handler correctly does this, but lots of MySQL-driven session
 > code does not.
 >
 > Example timeline:
 > 1. client sends a request
 > 2. session data is loaded from the db
 > 3. same client sends a request before the first one is finished (e.g.
 > frames, tabbed browsing, slow server response times, etc)
 > 4. session data is again loaded from the db
 > 5. the first request changes some values in $_SESSION
 > 6. the second request changes some values in $_SESSION
 > 7. the first request writes the data to the db and exits
 > 8. the second request writes it's data (over that written by the first
 > request) and exits
 >
 > PHP's native handler solves this problem by forcing concurrent requests
 > to wait for each other. The same thing needs to happen in a
 > database-driven session handler.
 >
 > SO, does anyone have some code that uses MySQL to replace PHP's native
 > session storage that also correctly handles this concurrency problem?
 > Ideally I'd like to see just a set of functions that can be used with
 > sessions_set_save_handler() to transparently shift PHP's sessions to a
 > database, but I'm not going to use the stuff I've found on the web or
 > even in books (appendix D of O'Reilly's Web Database Applications with
 > PHP & MySQL publishes code with this problem).
 >
 > Folks using database sessions who do not deal with this scenario be
 > warned! I'm surprised so much bad code is going around for this task...
 
 MySQL's InnoDB supports row-level locking. So row the right row in
 session_start and release it in session_close function.
 
 In MyISAM you can use application-level locking: GET_LOCK() and
 RELEASE_LOCK() in session_start and session_close, respectively.
 Parameter would be session id with some prefix.
 
 The problem is when you need to create session id - you must lock the
 whole table to find unused session id and insert it into table.
  Navigation: [Reply to this message] |