Generic Architecture for Caching Table Data: Supercharge Your Cache - Switching the cache on and off
(Page 2 of 4 )
When my code produces truly unexpected results, I always immediately suspect the cache: is it out of sync, does it contain corrupted data, and so on. So what would be an easy way to confirm whether the cache really is to blame? How about switching it off! That’s right, if you switch the cache off, and your code suddenly starts working, there must be something wrong with your cache; if it still does not work, you are going to have to dig deeper, but at least you ruled out the cache. Let’s see how we can implement such a switch.
You will first need to create the switch. This is basically a private global BOOLEAN variable that you declare in your package body and will signal if the cache is in use (TRUE) or not (FALSE).
g_caching BOOLEAN :=TRUE;
Here we default g_caching to TRUE meaning the cache is on by default.
In order for anybody to “set” the switch, we need a procedure, which we will make public by publishing it in the package specification:
PROCEDURE set_caching (p_on IN BOOLEAN DEFAULTTRUE)
AS
BEGIN
g_caching := NVL(p_on,TRUE);
END set_caching;
Some of you are probably wondering why we don’t just make our g_caching variable public and forget about the set_caching procedure. It is considered good practice to hide your global variables (all of them, not just this one) in the package body. You should never expose them because then you lose control over its content. Anybody can set your public variable to whatever they want, making it impossible to track what happens.
Using this technique, you have complete control over your global variable and you can add your own business rules. E.g. my business rule is that if NULL is passed in, I set the value to TRUE. If I had exposed the variable, I could not enforce my business rule, and somebody could have easily set it to NULL, probably breaking the caching logic further on. It is true that I could change all the other code to handle NULL values in my g_caching variable, but this is much cleaner (and easier!). I could also extend the set_caching procedure later on, adding some security measures (e.g. only allow certain users to set the switch). You can even log who sets the switch, what it was set to and when.
We also create a public function that can tell us whether the cache is on or off:
FUNCTION caching
RETURN BOOLEAN
AS
BEGIN
RETURN g_caching;
END caching;
Don’t forget to add these functions to the package specification.
Now we are ready to make our modifications to the caching logic. Here is the new code:
FUNCTION dept_data (p_dept_id IN dept.deptno%TYPE)
RETURN department_tp
AS
l_dept_data department_tp;
BEGIN
l_dept_data := read_from_cache (p_dept_id);
IF (l_dept_data.NAME IS NULL)
THEN
l_dept_data := read_from_db (p_dept_id);
IF ((l_dept_data.NAME IS NOT NULL)AND(caching))
THEN
write_to_cache (p_dept_id, l_dept_data);
END IF;
END IF;
RETURN l_dept_data;
END dept_data;
We do the check before we write to the cache. Notice though that we don’t check whether caching is switched on before we read. This isn’t really necessary as the cache would be empty anyway, forcing a DB read later on (you could add the check though if you want).
Anybody can now control the behavior of your cache (use it or not), by calling set_caching:
DECLARE
l_dept_data dept_cache.department_tp;
BEGIN
-- cache will be used: the default
l_dept_data := dept_cache.dept_data ('10');
-- Cache will not be used
dept_cache.set_caching (FALSE);
l_dept_data := dept_cache.dept_data ('10');
END;
Next: Don’t Forget to Flush >>
More Oracle Articles
More By Mark Vilrokx