Broken Materialized Views and ORA-12034
Monday, December 7th, 2009Suppose I have an 8 million row master table sitting in a database next to my desk in sunny Sydney. I stick a materialized view log on it, and create a fast refreshable materialized view on that master table in a database sitting thousands of kilometres away somewhere. Imagine further that the link between my desk and this remote is not exactly brilliant: copying the original 8 million rows across when creating the materialized view in the first place would have taken several hours. Let us say, therefore that it’s not a copying exercise I would be keen to do again, if I could help it!
Finally, imagine that on attempting a fast refresh on the remote materialized view you see the dreaded error message:
ERROR at line 1: ORA-12034: materialized view log on "LOCALDB"."BIGTABLE" younger than last refresh
There are several and varied reasons you might get that particular error message: if you drop and re-create the local materialized view log as part of a migration of that particular database from Windows to Linux, for example; so would purging the log. Whatever the reason, the usual advice at this point is to simply drop the remote materialized view and re-create it from scratch. But in this case, that course of action would result in a multi-hour data-copying-over-a-flakey-network nightmare writ large, so it’s not advice I would particularly want to follow.
Happily, there is a way around the drama that doesn’t involve multi-Gigabyte network copying.
1. Create a table as a copy of the current materialized view in the remote database. Since the copying of a table is entirely taking place within the remote database, no network traffic is involved:
create table mvbackup as select * from actual_mv;
2. Drop the existing materialized view in the remote database:
drop materialized view actual_mv; drop table actual_mv purge;
The drop table command is in there, just in case the materialized view was originally created on a prebuilt table. If it wasn’t, then the command will produce an error because no such table exists. Just ignore it if that happens, then.
3. Create a new table with the ‘right’ name as a copy of the backup taken at step 1:
create table actual_mv as select * from mvbackup;
4. Create a new materialized view on this newly created table, using the ‘on prebuilt table’ clause:
create materialized view actual_mv on prebuilt table refresh fast on demand as select * from master_table@australian_db
Now, at this point, there is a reference to the remote database -and there’s no doubt that the remote database goes across that link to check for the existence of the master table and so on. But the ‘on prebuilt table’ clause means that it doesn’t fetch any data across the link, because it knows that all its required data is stored locally. The net result is that the new materialized view is created in less than a couple of seconds, even with that reference to the remote database.
Of course, this technique only really works because I happen to know for certain that the master table is not undergoing any DML as I’m doing all this mucking about. It also helps that I know for a fact that no DML has taken place on the master table since the last refresh of the remote materialized view. I checked that was indeed the case with this simple query:
select * from master_table@australian_db minus select * from mvbackup;
Had anything been returned by that query, I would have inserted it into my backup table before starting step 2:
insert into mvbackup select * from master_table@australian_db where primary_key_col in (select primary_key_col from master_table@australian_db minus select primary_key_col from mvbackup);
That would have made the MV built at step 4 as up-to-date as its master, and would therefore have involved fetching data across the wire, slowly. However, at least it would only have been a tiny subset of the total data -a matter of a few tens of minutes at most, and not the multiple hours required to fetch the entire data set as would have been the case if I’d dropped and re-created the materialized view in its entirety.