Re: warning & question about mysql sessions & concurrency

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Mar 06, 2005 at 02:27:53PM +0000, Chris Smith wrote:
> 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.
>
> Neither do.

PHP absolutely does.  Take the following code:
<?
session_start();
if (!isset($_SESSION['count'])) $_SESSION['count'] = 0;
$_SESSION['count'] = $_SESSION['count'] + 1;
sleep(5);
echo "<html><body><h1>Current count:";
echo $_SESSION['count'];
echo "</h1></body></html>";
?>

Open up two browser windows/tabs and load this page in both, try to make
both pages load at the same time.  Notice the second request takes 10
seconds while the first takes 5.  That's because the second one is
really, actually, indeed WAITING for the first one to finish.  (You may
have to do a first initial request before trying this to get the cookie
set.)  This also is not a side effect of web server processes,
threading, etc., it's really waiting until the session lock is released.

> No request should be blocking (i.e. wait for concurrent processes to
> execute).  This implies a poor understanding of transactional processing
> from both yourself and PHP!

On the contrary, when dealing with a session store (in PHP, which AFAIK
always writes the session and the end of the request), it's very
important for serial access instead of concurrent.

Take the following sql from two MySQL clients:

client 1: start transaction;
client 2: start transaction;
client 1: select * from mytable where id=1 FOR UPDATE;
# i.e. "give me the data from the row with a write lock"
client 2: select * from mytable where id=1 FOR UPDATE;
...

client 2 is going to have to sit there and wait until client 1 commits
or rolls back.  that's how it should work with the session store.  each
PHP request should acquire a "write lock" on the session so no other
request can even *read* the data until the original request is done.

> - You usually only store some kind of identification for a user in the
> session - no other data.  doing otherwise is dangerous as there are
> multiple copies of data floating around uncontrolled.  A session-id is
> enough information to store.  Don't use the session for storing data
> willy nilly - it is for identifying the session only - nothing else.
> Can't say that enough.  Don't use it for shortcutting code.

there is no point to storing only a session id in a session store. the
session id is already in the cookie or querystring.  what's the point of
a session, then?  tell me how you store a user's login status, a user's
shopping cart contents, etc. - that is the place i call the "session
store" and that is the thing that needs to block concurrent
(write) requests, whatever you want to call it...

> - If you want a proper transactional system, there are two ways to
> handle concurrency:
[snip]
> Personally, no-one in the PHP/MySQL arena tends to understand these
> concepts as the two technologies are rarely used for pushing data around
> on big systems (this is generally Java/Postgres' domain).

i understand your explanations.  in the case of session concurrency, if
you're using a fail commit on change and are also using frames with
PHP's session design, you're site just isn't going to work.
one frame will appear and the rest will say "sorry, some other process
got to the data first".  instead, each frame request has to wait for
each other to finish, which is how PHP's native session handler does it.

> I ONLY use PHP/MySQL for knocking up quick web apps to fart out content
> - nothing serious because it's simply not suited.

Have you checked out InnoDB?  Row level locking, transactions, etc etc.
Not as fully featured, agreed, but all the critical stuff is there.
MySQL isn't the same as it was a few years ago.

/jw

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux