Dieser Post wurde aus meiner alten WordPress-Installation importiert. Sollte es Darstellungsprobleme, falsche Links oder fehlende Bilder geben, bitte einfach hier einen Kommentar hinterlassen. Danke.
Why should I write about sessioning at all? A session is something which exists and should be as easy usable as possible. Is this the end of my blog post about sessioning?
No, it isn't, because sessions usually don't make any trouble, but not always.
Long term lock
I was told that PHP does some session locking:- Lock the session ID
- Read the session data
- Process the request/run the script
- Write the session data
- Unlock the session ID
Here is a sample with two requests racing for the same session, each row happens at the same time:
Try to lock session | Try to lock session |
Got session lock | Wait |
Read session | Wait |
Run the script | Wait |
Write session | Wait |
Unlock the session | Wait |
Finished | Got session lock |
Read sesion | |
Run the script | |
Write session | |
Finished |
No lock
The lock is blocking the second (and all other) requests, why not simply remove it. All requests will run in parallel and everything is fine - but it's not that easy. The session might have a simple counter which is increased by every page access:Read the session | Read the session |
Current counter value: 5 | Current counter value: 5 |
Increased counter: 6 | Increased counter: 6 |
Write the session | Write the session |
You might think that this race condition is pure theory, but it isn't. There are common browser plugins - at least for Firefox and Opera - which open all links within a rubberband in new tabs. I like this, for example for opening a list of tickets in our ticket system instead of shift+click on every single link.
Synchronous storage access
Locking seems to be no option, but skipping the "read the session" part might be one. Perl could easily tie a hash to a module and pass every read or write access to the hash directly to a function of the module. Each read or write access to the session hash is translated into a function call, for example:sub FETCH { my ($tied_item, $key) = @_; my @result = $DBH->selectrow_array( 'SELECT '.$DBH->quote_identifier($key).' FROM session_data WHERE id=' . $DBH->quote($tied_item->{id}) ); return $result[0];}
Every operation will work directly on the database. The counter sample from the "no lock" sample still might end up in a race condition as both requests might fetch the value, increase it and write it back at the same time. I experienced a project not long ago where a mySQL cluster was in use and the requests are waiting (shortly) until the slave is fresh. Two requests waiting for the same slave may be started with a (slight) delay but still run absolutely parallel from the "wait for slave" function until the end - and they did, resulting in duplicate data in a table where data must be unique. An existing unique index showed the problem, because one of them ran into a "duplicate key" error just after checking if the key exists, but problems are very less likely using synchronous storage access because the time where races might happy rapidly decreases.
Synchronous atomic storage access
Another approach doesn't use a hash at all but a session object which has get_value, set_value and some other functions. They face the same problems like the tied solution before except that operations with race-risks might be done atomic.A atomic operation happends as one step. A inc_value method is a very good example:
sub inc_value { my $self = shift; my $key = shift;There is no read, increase and write, everything is done in a single SQL command. Thousand or more requests might run parallel, but the counter will always have the correct result.my $quoted_key = $DBH->quote_identifier($key); $DBH->do("UPDATE session_data SET $quoted_key = $quoted_key + 1");}
Using a custom session class/module isn't as easy as simply using anything provided from your framework, but it gives you much more control about what's happening.
Non-atomic operations (which require custom source to run between loading data from the storage and writing it back) may add locking again for very short-term locks on a session but they need additional care from the developer when and expecially how long to lock the session.
Noch keine Kommentare. Schreib was dazu