Greg Troxel wrote:
> I don't quite understand what is going on. I think the error happened
> on the INSERT, but on reflection this is because of two similar
> transactions:
>
> delete foo if foo is there
> insert bar
>
> and the point is that the delete doesn't fail. Your patch is to try to
> catch the delete failing, and skip the insert. But I would expect the
> delete to return DELETE 0, which doesn't seem like an error:
>
> trac-redacted2=# delete from session_attribute where sid = 'no-such-user';
> DELETE 0
>
> Is this because we are running read committed instead of full
> transactions? We are having the second transaction to do the insert see
> database state from before the first insert is committed.
Yes you're right. It's the INSERT statement and not the DELETE statement
that might fail if another transaction manages to execute and commit
between the DELETE and INSERT of the first transaction (if read
committed is being used).
I somehow managed to wrap the wrong cursor.execute statement with an
exception handler.
I've attached an updated version of the patch.
Thanks for spotting this!
/ Jonas
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Trac
Users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/trac-users?hl=en
-~----------~----~----~----~------~----~------~--~---
Index: trac/web/session.py
===================================================================
--- trac/web/session.py (revision 7647)
+++ trac/web/session.py (working copy)
@@ -97,9 +97,16 @@
(self.sid,))
self._old = dict(self.items())
if attrs:
- cursor.executemany("INSERT INTO session_attribute "
- "(sid,authenticated,name,value) "
- "VALUES(%s,%s,%s,%s)", attrs)
+ # The session variables might already have been updated by a
+ # concurrent request.
+ try:
+ cursor.executemany("INSERT INTO session_attribute "
+ "(sid,authenticated,name,value) "
+ "VALUES(%s,%s,%s,%s)", attrs)
+ except Exception, e:
+ db.rollback()
+ self.env.log.warning('Attributes for session %s already '
+ 'updated: %s' % (self.sid, e))
elif not authenticated:
# No need to keep around empty unauthenticated sessions
cursor.execute("DELETE FROM session "