How cache invalidations work (and hack to listen in) (was Re: Applause for ZODB! And a question: How do you get pending change info from a transaction object?)
Jim Fulton <[email protected]> Wed, 2 May 2018 07:31:15 -0600
| Newsgroups | gmane.comp.web.zope.zodb |
|---|---|
| Message-ID | <CAPDm-Fifh3FiHW9mVSH89OwyZsySbjmkTMYBbKmD-Ka=gKqUgg@mail.gmail.com> |
A wildly useful, but subtle feature of ZODB is that it has a *transactionally consistent cache*. Applications don't have to worry about cache invalidation. Data in the cache is always consistent with the database snapshot (https://en.wikipedia.org/wiki/Snapshot_isolation) they see, based on transaction start time. The way that ZODB does this is via object invalidations. Clients get invalidations for objects modified in transactions. At the start of a transaction, invalidations are used to remove state for any objects in the cache that were modified. Subsequent reads inside the transaction get object data as of the transaction start time. The way this works differs for RelStorage and other storages: - For RelStorage, at the start of a transaction, RelStorage queries for new invalidations (since the last poll). This *pull* strategy likely allows RelStorage to scale to more clients, because multiple invalidations aren't sent for frequently-changing objects and because invalidations aren't sent to idle clients. A disadvantage of this approach is that every transaction makes at least one round-trip to the server. - For other storages, invalidations are pushed to clients as transactions are committed. These invalidations are buffered and applied at transaction starts. Theoretically, this can cause a lot of network transaction, although, to my knowledge, no one has ever demonstrated this to be significant. I suspect that this is not significant. Because this is asynchronous. Many read transactions require no server round trips. On Tue, May 1, 2018 at 8:30 AM, David Pesta <[email protected]> wrote: > Yes, the hack you mentioned will be helpful if it's not too much trouble > to share it. So that I can get started on something. > So, to get notified when objects change: For non-RelStorage storahe, a storage adapter, https://github.com/zopefoundation/ZODB/blob/c75a197deebc3a65aa521bda11bdaa83dadd8b48/src/ZODB/mvccadapter.py, provides, among other things, invalidation buffering. When a storage (including a local storage like a file storage) sends invalidations to the client, the invalidate method, https://github.com/zopefoundation/ZODB/blob/c75a197deebc3a65aa521bda11bdaa83dadd8b48/src/ZODB/mvccadapter.py#L77, is called that broadcasts invalidations to instances for each local database connection, which cache the invalidations for the next transaction. On very rare occasions, an invalidateCache method is called to indicate that the entire cache should be invalidated. I suggest ignoring this for now. Soon, I'm going to provide a public API to subscribe to these invalidations. In the meantime, you can monkey patch this method to call your code in addition to what it's doing now. Something like (untested): invalidate_orig = MVCCAdapter.invalidate def invalidate(self, transaction_id, oids): my_subscriber(oids) invalidate_orig(self, transaction_id, oids) MVCCAdapter.invalidate = invalidate Jim -- Jim Fulton http://jimfulton.info -- You received this message because you are subscribed to the Google Groups "zodb" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.