Optimistic locking in v2?

Hi,

I messed with this subject for some time now. To the best of my knowledge there is no optimistic locking in Yii v1.x.

Having some sort of solution for concurrency problems is a must in any web application besides the most trivial ones, due to the concurrent nature of a web app. I think that if Yii v2 would have some sort of solution that would be very good for alleviating Yii’s value for anyone who’s smart enough to appreciate this. To me, if its going to enter, it will part of the ‘professional’ slogan of Yii.

If it is considered, here’s some suggestions:

  • Do have a “StaleObjectErroeException” of some sort. Its important that application specific logic could determine what to do in the case of stale object being attempted saving. In some cases the logic will be to try several times and then fire a more ‘conventional’ exception (e.g. CHttpException). In other cases the logic would be to ignore this exception as present the user with the same “thank you for doing this or that” message.

  • Its important to have the optimistic locking in the ‘standard’ API calls like save() or update() as those are used for example if beforeSave() is desired (kind of like the full fledged API methods, contrary to using the aux methods like updateByPk()).

I am aware of this forum thread and also initiated during my research on optimistic locking that forum thread. Both are relevant.

Thanks!

Boaz.

I really get your point and I know that this is a very useful feature BUT the idea of Yii is to provide you with the most basic and non-bloated piece of code that is used in 99% of all cases and I personally think that versioning is something that should explicitly implemented by the developer. However, the way one has to go to implement this is really tedious (basically replicating CActiveRecord just for this simple case) and prone to error. That brings me to another point: It should be easier to extend CActiveRecord itself to make life easier. I am thinking about a base class that could be extended more easily.

I disagree. I think that optimistic locking is an killing feature and a feature that will lure enterprise users.

As for the implementation, I have already implemented it myself, by the way of extending CActiveRecord and having all my model extend this class. In it I have: safelyUpdateByPk(), safelyDeleteByPk() and safelyUpdateByPkWithRetry() which is the same as the update method, but also accepts two more parameters - number of retries and interval between retries. My implementation works (I think :) ) but I think that this deserves to be in the CActiveRecord API directly.

Just MHO… and thanks for the feedback!

I would say you should create a pull request on Github as soon as Yii 2.0 alpha is available and see what the core members think about it. As long as it is really unobtrusive and configurable you might have a chance of getting it into the core yourself ;)

I’m wondering if that’s another usecase for intercepting behaviours in CActiveRecord …

What’s “intercepting behaviors”? I’ll be happy for some information/links. For all I know, behaviors are a way to “dress” a class with extra functionality (methods), kind of a “poor man’s multiple inheritance”.

Thanks!

That are behaviours with the power to intercept method calls such as findByPk() etc. A bit like what filters are to controllers. This would allow for more fine grained query caching or even identity maps.

Gotcha.

Could very well be such a case, but wouldn’t it be cleaner to have it directly in the API? Is “optimistic locking support” directly in the API doesn’t fit right? I don’t think that by principal this is a feature that should be out of the (lean and mean) framework itself. I know that there are good frameworks that include optimistic (and pessimistic) locking.

But then again, getting it done is a matter of resource allocation I guess more than theoretical argument and I cannot help much with the available resource that Yii dev team has (or that I have… :) ).

Boaz

That’s very application specific and depends on what backend you’re using to store your data. Sometimes it’s required to use pessimistic locking, sometimes you want to actually try merging changes automatically, sometimes you want just to overwrite changes. In some cases it’s much more better to rely on DB isolation levels rather than on the code.

Hi samdark:

It doesn’t have to be a case of full blown solution or nothing. I think that optimistic locking API methods only, that include a matching “int” locking field in the relevant AR class/table (“lock version” indicator), and a little warning that while “safer”, those methods sacrifices just a little bit of performance, is feasible and isn’t dependent on specific DB. Other needs or cases, such as pessimistic locking are not included in this improvement, but nor do they are likely to contradict with this improvement, should the time come to handle those as well (if at all - I agree that more complicated solutions are starting to introduce complexity like DB specific peculiarities).

Also, I want to state that I wish I had the resources to help (be the resources time, experience, etc). Unfortunately I don’t. I’m rather new in the Yii neighborhood and my time to contribute will come soon enough, I hope.

Boaz

All this sounds like a good candidate for a behavior. In Yii2 we’ll have new events system so this one will fit. Maybe we’ll even include it into the core or mark as officially supported extension.

Nice. Having such a thing as a behavior makes the application design even more modular (in comparison to some master class) - plug, prey and hopefully play - or to the ashtray :)

Y2 will gotta have good documentation from the start, but I guess this is off-topic to this thread.

I think I’ve read that Yii2 AR will hold the original values that have been loaded from the storage. And we will have some property/method to check if the data has been edited or not … IsDirty() or something like that.

If it is the case, then we can implement an optimistic locking without an additional column for version controlling … as they are doing in .NET-Framework.




update some_table

set col_a = val_a, col_b = val_b, ... col_n = val_n

where col_a = val_a_org and col_b = val_b_org and ... col_n = val_n_org



I’m not into the details of the suggested design. Skimming through it, I think that isDirty() would not be good for optimistic locking: even if calling this method will trigger a check against the DB (which I’m not sure of - possibly it refers to the state of the object at hand after you’ve read(=instantiated) it) and even if you check “just before” the saving, there’s still little time between the check and the actual save - and this will lead to problems and its hardly a locking of any kind.

The check and saving should be atomic and since the save is done in the DB, the check should be there as well, in a single atomic action together with the saving.

Today I achieve this with updateByPk() that is called with a $condition, which is translated to an SQL statement that resembles “[font=”'Courier New"]UPDATE tablename set some_col = “value” [color="#0000ff"]WHERE lock_version=135[/color][/font] (in blue is the condition which makes this atomic and guarentees the data integrity, at the end of the day(=request :) ).

Your second paragraph isn’t related to the isDirty directly, but rather relies on the AR object to retain the original values it was filled with when instantiated. If that’s going to be in Yii’s v2 AR then indeed no extra column for version checking is needed but rather a check with your suggested code could do it. But, notice that on tables with lots of columns its possible that a single “lock_version” column to check will give better performance than the suggested check that will compare lots of columns, and also this is error prone while coding.

Well, I meant to say that yii developers can make use of the stored values for dirty checking to implement an optimistic locking version of updateByPk().

And, yes, the performance penalty could be an obstacle, but they are doing this in .NET.

Well, Yii and PHP communities do not hold the world by the b&^$s (at least, that’s how I see things where I live - Israel - the “the dot net nation”) so the those communities cannot afford to act as Microsoft… :) . If there is a workaround over the performance penalty in the first place why not take it? The extra column seems like a little burden to me.

In any case, I think we’re putting the cart before the horses… :) .

Okay, I think I’ve got your point, and hopefully you’ve got mine.

We have different opinions but it’s OK with me. :)

BTW, I don’t really care Yii and PHP people could have adopted some nice idea from microsoft, if any.

Indeed, the naming convention of Yii core classes reminded me of those in MFC. ::)

I agree - good ideas are good to be inspired by, no matter where they came from.