Angus Lees wrote:
At Tue, 13 Jul 2004 12:30:42 +0200, RobertCZ wrote:Gerald Richter wrote:I tried to play with it and it seems that Postgres as a store does SELECT ... FOR UPDATE,To me it looks like only one Apache child is working and other are just waiting for session commit.Mmmh, yes this seems to be the case. I am not sure how select for update works, for the other storages the locking works the way, that multiple pages can read at the same time, only if one page writes it tries to get an exclusive lock. So just do write only at the end of the page, normaly solves this locking problem.If thats what every other storage does, then every other storage has a pretty severe race condition. This is fine if the data you are storing in %mdat (or %udat) isn't dependent on what the previous %mdat data was (eg: storing "the last visitor" is ok, a page counter is not ok). The problem is that perl cannot know when fetching the session data, whether you are intending to modify it or not. It seems the Postgres backend is taking the conservative approach, unlike every other Apache::Session store (and against the behaviour described in the Apache::Session docs). Well, Apache::Session docs say: If you retrieve an existing session, Session immediately restores the object from storage [....] also obtains an non-exclusive lock on the session....
I believe that using simple read locks is plain stupid for %mdat because it works in most simple cases only, eg your 'last-visitor' example. Even in %udat you can get quite easy two childs writing to the same session, it is enough if user just clicks faster then backend processes requests (think of page with frames or long processing or SOAP etc). And when some updates are lost and the last child wins, your application is f* up. I propose - use write lock for %udat and %mdat as DEFAULT ( Transaction => 1 ) and saying that very loudly in the docs - reverse %mdat back to the per-module behaviour or remove it completely - maybe add %adat for application data that would be just a simple alias to some per-app global hash (and warn %adat will not survive apache restart, unlike udat/mdat) Gerald? PS. When I try to empty %mdat, maybe in base.html like [- delete $mdat{$_} foreach keys %mdat; %mdat = (); -] it dumps empty session as expected. Now I comment out those delete lines and reload and %mdat has the same content as before delete. What's wrong?Deleting all keys like this also deletes _session_id. Its very silly, but it seems the only place Apache::Session stores the session_id is actually in $self->{data}->{_session_id}. In lieu of anyone actually fixing this Apache::Session stupidity - you will have to do something like this instead: [- delete $mdat{$_} foreach grep !/^_/, keys %mdat -] Ups. I should have thought of this... :-( Thanks, Angus. |
- mdat/postgres - major perfomance problem? Robert Germic
- Re: mdat/postgres - major perfomance problem... Gerald Richter
- Re: mdat/postgres - major perfomance pro... Gerald Richter
- Is there a point in using the reques... John P. Gibbons
- Re: Is there a point in using th... Luiz Fernando B. Ribeiro
- Re: Is there a point in using th... Gerald Richter
- Re: mdat/postgres - major perfomance pro... Angus Lees
- Re: mdat/postgres - major perfomance... RobertCZ
- Re: mdat/postgres - major perfom... RobertCZ