From: Sidnei da S. <si...@aw...> - 2003-10-27 23:00:12
|
| >Ok, I think I'm starting to understand what fits where now. I think | >that the problem is that I was using the same connection for different | >transactions here. | | The terminology is confusing, I have to change it sometime. A | DBConnection can be used directly. Or you can create a transaction | from the DBConnection. The DBConnection still controls that | transaction, but the transaction takes the place of a connection for | the SQLObject instances. "Connection" is a confusing word -- each | transaction is a connection. Each transaction is also incidentally | tied to its own database connection, but they all share one | DBConnection (subclass) instance. This makes it sound complicated, but | it's just the poor terminology. The tricky part for me is that I'm not using the SQLObject Transaction class, but instead, I'm wrapping DBConnection on a Zope-specific Transaction class. :) | >1. The transaction is rolled back, the objects are in invalid state | >and should be purged from cache | | This basically happens. Instances aren't purged from the | connection-level cache, but column values are purged from each | instances' personal cache (that's what .expire() does). | | >2. Transaction is commited, the objects are valid and the cache is | >valid. | | Yes. Great! | >AFAICS, in the current implementation, the state of 'x' from | >transaction '2' would override the state of 'x' as saved by | >transaction '1'. Does that sound correct? | | To clarify, we're talking about "object with id x", which is actually | two instances. | | Yes, transaction 2 will just clobber 1. This is what other people have | talked about as optimistic locking, and it requires adding special | support in SQLObject. | | I think it will mean something like a magic last_changed column in | SQLObject tables, which gets updated each time a change is made (but | you can't update it manually). Then each time you do an update you add | "WHERE id = <my ID> AND last_changed = <my expectation of | last_changed". Then you test how many rows your query effected | (cursor.rowcount I think, but this might be database driver specific), | and if you get 0 then you raise an exception. last_changed could | probably be an integer, with the value of time.time()*1000 (will that | get too big for databases?). Probably yes. I think that requiring a last_changed column in each table may not be a good idea though. As long as we just care for changes that happen when two transactions overlap, we could just have a module-level registry of objects that changed on a transaction, then we wouldn't need any change to the databases at all. Note that if there are two separate transactions which dont overlap, last_changed is meaningless, so not useful. <snip part about connections x transactions > | Yes, fetching the same object within the same transaction will give you | back the object that has already been created, and is pretty quick to | do. If a transaction implicitly is restarted after a commit or | rollback, then you can even reuse the transaction and have the benefit | of a valid cache. Amazing. Theres one last question now: currently the transaction is implicitly restarted or not? OT: I changed my code to have a connection cache of one connection per thread, so I guess this is going to be just enough for my needs *and* still have the benefit of a connection cache that lasts through transactions. I have to check more throughly that the rollback is clearing the instance cache though, because I'm using my own Transaction class. -- Sidnei da Silva <si...@aw...> dreamcatching :: making your dreams come true http://awkly.org Any sufficiently advanced bug is indistinguishable from a feature. -- Rich Kulawiec |