This is part 4 of a post series about EBR.
In part 1 we created the baseline model and code – a table (PEOPLE) and two packages (PEOPLE_DL and APP_MGR).
In part 2 we saw that even a simple change – a package body compilation – can be dangerous in a busy system.
In part 3 we learned about editions and how they can be used for solving the problems described in part 2, so changes can be applied in both online and safe way. I discussed enabling, creating and using editions; session edition; and editioned objects.
In this part we’ll see more challenges that online upgrades bring – this time when changing a package spec.
Visit the index page for all the parts of the series
Invalidation
This time we need to change the PEOPLE_DL package spec. There are no table changes, and of course, as we speak about EBR, the upgrade from the previous version to the new one should be online.
An online upgrade means that the application users should be able to continue working uninterruptedly. The code objects that they use should remain valid and available at any time.
In addition to the challenges raised from the first use case – changing PEOPLE_DL package body – the current use case introduces another challenge: invalidation. Changing the PEOPLE_DL package spec will cause its dependent objects become invalid.
Even if the change does not cause any compilation errors in the dependent objects, they become invalid.
Actually, even if we just recompile an object, without making any changes in it, its dependent objects still become invalid.
Now, it’s true that in these cases revalidation will occur automatically as soon as the invalid object is used, but in an online upgrade scenario this is usually unacceptable.
Moreover, many times we need to change multiple interrelated objects. For example, changing the API of some procedure in one package, and consequently changing it in the package body and changing the calls to that procedure from another package. In this case we cannot avoid having broken objects – invalid and with compilation errors – during the upgrade, and this is obviously cannot be really considered an online upgrade.
The Transaction Concept
It would be nice if we could compile all these objects in a single transaction, as one atomic operation, so at any point of time the users will see only a consistent view of all the objects – and all of them in a “Valid” state.
Well, actually, editions allow us to achieve this concept. We make all the changes in a new edition, and expose the new edition to the clients only when all the objects are valid.
Actualization
We start this post’s example at the same point we ended the previous post. We have two editions and four editioned objects. In the V1 edition one of the objects – the PEOPLE_DL package body – is actual, and the other three objects are inherited from the OR$BASE edition:
Now we want to change the PEOPLE_DL spec, and we already know that the safe way to do it online is by using a new edition.
So we’ll create edition V2 and we’ll compile the new version of the PEOPLE_DL spec in V2, so the PEOPLE_DL spec will be actual in V2, like this:
But something is very wrong with this picture. Recall the following statement from the previous post:
By definition, when we are in the context of a specific edition, we see and use the objects that are actual in this session and the inherited objects from ancestor editions, but never objects from descendant editions.
This observation may seem trivial, but in my opinion it’s the cornerstone of EBR. This is what lets us apply the new or changed code in the privacy of a new edition, where no client is exposed to the new version until we want to expose it.
In the picture, the PEOPLE_DL package body from V1 and the APP_MGR package body from ORA$BASE refer to the spec from V2, and this violates the “privacy rule”.
It means that whenever an object becomes actual in some edition, all its dependent objects must become actual in this edition as well. In our case, the correct picture is this:
Now, I have good news, bad news, very bad news, and really good news.
Good News
The good news is that this actualization of dependent objects happens automatically.
Bad News
The bad news is that it happens too late. It doesn’t happen when we actualize the object, but only when the dependent objects are used (just like with regular revalidation), and that means we cannot count on the automatic actualization in an online upgrade scenario.
Very Bad News
The very bad news (in my opinion, of course) is that once we actualize an object in the new edition, we get a false and very misleading picture from the data dictionary views, until the dependent objects are actualized as well:
- By looking at the USER_OBJECTS view it seems that we still inherit the dependent objects from ancestor editions, although this is impossible under the EBR rules.
- There is no indication that the dependent objects became invalid as a result of the actualization.
- The dependencies from the dependent objects to the object we’ve just actualized disappear from the USER_DEPENDENCIES view.
All of this is a direct consequence of the fact that the actualization of the dependent objects is delayed.
Really Good News
So what is the really good news?
That once we know and understand this behavior, it’s easy to deal with it.
In the next post I’ll show how, as well as examples for everything described in this post.
For other parts of the EBR series, please visit the index page.
Maybe I have to wait for the next part of this excellent blog series on EBR but I fail to understand the following statement:
“By looking at the USER_OBJECTS view it seems that we still inherit the dependent objects from ancestor editions, although this is impossible under the EBR rules.”
Is this not the “normal” correct behavior you’d expect from EBR? The other way around would be a violation of the EBR rules. In a specific edition you would not expect to see dependent objects from descendant editions. Or am I missing the point?
Thanks for your comment Marcel.
When our session edition is V2 (the new one), the correct picture is having the dependent objects actual in V2 (same edition, not descendant).
The wrong picture, which is what we see until the consequential actualization happens, is that the dependent objects are inherited from ancestor editions (V1 or ORA$BASE). This is a violation of the EBR fundamental rules.
Anyway, I think this will become very clear in the next post, which I’ll dedicate to demonstrate what I wrote in this post. So stay tuned 🙂
Thanks,
Oren.
Hi Oren,
Thanks for the articles, they are very usefull.
However I cant understand how to deal with the old editions. Suppose, DBA compiled the new version of the package and moved all the sessions to the new edition V5. As you can’t delete V4, V3.., so they remain in the DB forever, even though all editions V4..V1 are not needed anymore.
As an alternative, we could compile the same package twice:
1. Compile your package in V5 and move the users to V5
2. Once all users are moved to V5, compile it again in ora$base and move the users to ora$base. Thereafter remove V5..V1
Please correct if it’s wrong.
Cheers, Nariman
Thanks for your comment Nariman.
I will dedicate at least one post in the series (probably more) for this issue.
In short, if all the users use edition V5, and no object is inherited in V5 (i.e., all the objects in V5 are actual), you can simply drop ORA$BASE, V1, V2, V3 and V4, in this order. It does require some preparations, but they are fairly simple (for example, changing the database-level default edition from ORA$BASE to V5).
Thanks,
Oren.