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). Removing the "FOR UPDATE" phrase from Apache/Session/Store/Postgres.pm should make Postgres behave in the same way as other stores - with the same race. Btw I notice that the Oracle store also uses FOR UPDATE. (SELECT ... FOR UPDATE takes a write lock on the selected rows until the end of the current transaction) > [...] postgres indeed does wait for first select for update to > finnish - however only if it's in explicit transaction so one has to > call BEGIN before and be in the AutoCommit => 0 mode Yes, AutoCommit => 1 makes "the end of the current transaction" occur immediately, dropping the FOR UPDATE locks after the SELECT is completed. > I'd love to use %mdat for all kind of neat trick namely for inter-user > sql query caching, inter-user application locking (so 2 users don't edit > the same record on the same web form etc), maybe track currectly > connected users etcetcetc but this locking thing has to be fixed For some of these cases (particularly caching), I think %mdat is the wrong place to store them. IMO, you're better off simply storing them as perl "globals" in a perl namespace of your choosing - no locking, no contention, no delay in retrieval. For things like prepared DBI statement handles, these can't be stored outside the perl process (in %mdat) anyway. > I guess only real way to fix this problem is patch Apache::Session and > Embperl to support read-only sessions, but that would be quit a lot of > patching. Perhaps we could just reduce the impact by having a "per file data" hash again? Then contention would only occur if multiple requests used the same embperl file, rather than every request for the same application. > >>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 -] -- - Gus --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]