db-jdo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Joerg von Frantzius <joerg.von.frantz...@artnology.com>
Subject Re: Cache invalidation
Date Tue, 07 Feb 2006 00:37:55 GMT
Hello Wes,

thanks for that analysis, I must admit I haven't really thought of what 
this means with optimistic txs!

While it is good that a stale read under optimistic transactions won't 
lead to wrong persistent data under any circumstances (your #2), I'd 
rather like to avoid optimistic verification exceptions where possible, 
though.

Concerning #1: the point with reading from P-NT instances outside 
transactions for me is that read-requests can be satisfied from cache 
without round-tripping to the DB. For a typical web-application that you 
can browse, and where most requests are read-requests, I find this the 
most effective. Now if my P-NT instances are never invalidated/hollowed 
out, e.g. because they never take part in a datastore transaction, I 
might be showing wrong information to the user, which, depending on the 
application, can be highly undesired.

The next thing I'd consequently ask for is that P-NT instances are in 
fact made transactionally consistent, in that they should also be 
hollowed out automatically if they have siblings by id that went from 
P-dirty to P-clean in some transaction. That's what I currently must 
imitate in a clumsy way after each transaction

This all would make P-NT much more safe to use, and more useful in 
consequence, IMHO...

Regards,
Jörg

Wes Biggs schrieb:
> I agree that it would be nice to change the method signatures to 
> "evictById" for those that take OIDs in order to avoid confusion.
>
> To clarify what I mean about persistent nontransactional objects, see 
> section 5.6.1 of the spec:
> "A persistent-nontransactional instance transitions to 
> persistent-clean if any managed field
> is accessed when a datastore transaction is in progress. The state of 
> the instance in memory
> is discarded and the state is loaded from the datastore."
>
> If you are running with an optimistic transaction instead, you'll get 
> an optimistic verification exception at commit time.  So I guess it is 
> possible to read stale data from the instance in the PM cache under a 
> couple of scenarios:
>
> 1. Reading previously loaded fields of a P-NT instance outside of a 
> transaction.
> 2. Reading previously loaded fields of a P-NT instance inside an 
> optimistic transaction.
>
> In these cases, I think you're right that it would be necessary to 
> hollow the instances in order to be absolutely sure that no stale data 
> is read after a L2 cache evict().
>
> On the other hand, if you're in an optimistic transaction, don't you 
> want to retain the previously read values (they represent the ACID 
> guarantee from the optimistic transaction)?  So the only case where it 
> might make sense to me is #1 above, and that seems debatable to me.  
> Do most people using P-NT objects expect them to be consistent with 
> the L2 cache at all times?  Or are they expected to act like a limited 
> form of an optimistic transaction?
>
> I don't have a strong opinion about this, I'm just trying to fully 
> articulate the question.
>
> Wes
>
> Joerg von Frantzius wrote:
>
>> Hi Wes,
>>
>> thanks for your answer, please see my comments below.
>>
>> Wesley Biggs schrieb:
>>
>>> Joerg von Frantzius wrote:
>>>
>>>> The problem here is that either evict() accepts only PC objects, 
>>>> not object ids, so we have to call PM.getObjectById() beforehand. 
>>>> If no object for that id was present, we're instantiating a hollow 
>>>> object here only to discard it afterwards, that's not very effective.
>>>
>>> I'm not quite parsing your "either" here, sorry.  But 
>>> DataStoreCache.evict() accepts object IDs.  I'm not sure I see the 
>>> necessity of calling PM.evict() as well, unless you have some 
>>> particularly long-lived transactions.
>>
>> We're doing nontransactional reads on long-living objects, so I 
>> guessed we needed to call PM.evict() to avoid accessing stale field 
>> data.
>>
>> You're of course right about DatastoreCache.evict() accepting IDs, 
>> thanks for pointing that out. I had just seen the same method 
>> signature, and so I assumed the parameter semantics also being the same.
>>
>> Calling it evictById() probably would be less misleading, even more 
>> so as a mistake here won't show up immediately. Also, if you only 
>> have a jar without sourcecode, the signatures are absolutely 
>> indistinguishable (Which of course is not an excuse for not having 
>> read the spec thoroughly enough ;)
>>
>>>> As we really want cache invalidation here, not eviction, this is 
>>>> even worse. For this purpose, it would be far more convenient to 
>>>> have some method like invalidateCachesFor(Object id) on 
>>>> PersistenceManagerFactory. 
>>>
>>> That's the intention of DataStoreCache.evict().  The semantics are 
>>> different than PM.evict().
>>
>> Only now I start understanding that I was misled by the word evict() 
>> for the L2-cache: as the user never gets hold of an L2 cache object 
>> anyway (a L1-cache object will be created for that), he shouldn't 
>> need to care whether the L2 cache internally needs to throw away 
>> (evict) some object in order to invalidate cached state. Spec says 
>> "/The evict methods are hints to the implementation that the 
>> instances referred to by the object ids are stale and should be 
>> evicted from the cache./" It might be nit-picking, but I think it 
>> would be clearer if the method was called invalidateByÍd(), which 
>> would be natural for some cache interface, and if the explanation 
>> said "/that the object state referred to by the object ids should be 
>> discarded/"
>>
>> Also, the spec doesn't say anything about DatastoreCache.evict() 
>> having any impact on P-nontrans instances. So I still need to go to 
>> every PM and evict there as well, which is very inconvenient.
>>
>> Or does the "evict" row in table 2 for P-nontrans really apply to 
>> /both /evict() methods, not only PM.evict()!? The RI JPOX isn't doing 
>> anything like that, by the way.
>>
>>>> To make our wish complete ;) this method would transition all 
>>>> non-transactional instances to hollow for that id, for all the PMs 
>>>> the PMF has given out. All transactional objects with that id 
>>>> should be transitioned to hollow after their transaction has 
>>>> completed (either with commit or rollback).
>>>
>>> Persistent nontransactional instances will have to be revalidated 
>>> against the datastore (or cache thereof) before being re-enlisted in 
>>> a transaction anyway.  The behavior you mention is a good way to 
>>> implement that, but it doesn't need to be mandated (hollow is not a 
>>> user-visible state).
>>
>> I'm not sure what you mean by mandating here? I'd just like to make 
>> sure that invalidated non-transactional instances will reload state 
>> upon next read access, without having to iterate all PMs. Also, I'd 
>> rather not like a call to PM.getObjectById() afterwards returning a 
>> new Java object for the same id, which I guess is the case after 
>> calling PM.evict(PM.getObjectById(id)).
>>
>> If a method invalidateById() existed, I'd see the sense of evict() in 
>> releasing the associated memory. evict() currently does two things at 
>> same time: evicting and transitioning to hollow. For (distributed) 
>> cache invalidation, I find it sensible to desire only the latter.
>>
>> Regards,
>> Jörg
>
>
>
>


Mime
View raw message