|
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]
|