Oracle物化视图日志及物化视图注册信息
Oracle物化视图如果要快速刷新,必须在主表上建立物化视图日志。Oracle通过物化视图日志来记录主表发生变化的行和上次刷新时间,快速刷新时就是更新上次刷新之后发生了变化的行,这就是快速刷新的原理。物化视图日志的内容会在刷新之后清除,否则的话,物化视图日志必然不断增长,因为它记录的是主表的变化,其记录数也许比主表还要多,因为主表某一行生成更新,主表记录数不会增加,但物化视图日志也要增加一条记录。那么,通过物化视图快速刷新,将一个主数据库的数据分发到多个数据库可不可行呢?会不会其中一个子数据库执行快速刷新之后物化视图日志就被清除了,其余站点再执行快速刷新将刷新不到数据呢?经过实验证明,这种情况是不会出现的,物化视图日志只有在全部子数据库都刷新之后才会被清除。说明Oracle是知道某个表上建了几个物化视图(快照)的,不管是本地物化视图还是远程物化视图,建物化视图的时候Oracle都会在主表所在数据库日志中记录了物化视图信息,通过视图DBA_REGISTERED_MVIEWS可以查询注册的物化视图信息,包括基表、物化视图所在站点(MVIEW_SITE)物化视图ID(MVIEW_ID),每创建一个物化视图,这里就会增加一条记录,每删除一个物化视图这里也就删除对应的记录。另外,视图DBA_BASE_TABLE_MVIEWS记录了每上基表上的物化视图的ID和最后一次刷新时间,每个物化视图刷新成功之后,这里的最后一次刷新时间就会被更新,下一次再刷新就会只刷新物化视图日志中SNAPTIME$$列值更新的行。而物化视图日志中的记录是否清除,则取决于这个视图中最后一次刷新时间(MVIEW_LAST_REFRESH_TIME列)最小值,物化视图日志中SNAPTIME$$大于MVIEW_LAST_REFRESH_TIME最小值的记录都要被保留,就使得其余数据库中的物化视图可以继续利用日志进行快速刷新。
现在就有一个问题,如果远程物化视图没有被正常删除(远程数据库崩溃、远程链接失效的情况下删除物化视图或者主数据库关闭的情况下删除了远程物化视图等等),则DBA_REGISTERED_MVIEWS中的信息是不会相应地被删除的,DBA_BASE_TABLE_MVIEWS中的信息也不会被删除和更新,那么物化视图日志就会为这些不存在的物化视图保留信息,浪费表空间,也会降低正常物化视图的刷新速度。这时就需要用DBMS_MVIEW.PURGE_MVIEW_FROM_LOG(MVIEW_ID)这个存储过程来清除物化视图日志,这个存储过程不会清除物化视图日志中不需保留的记录,还清除了多余的物化视图注册信息,所以可以彻底解决远程物化视图没有被正常删除的问题。存储过程DBMS_MVIEW.UNREGISTER()可以删除多余的物化视图注册信息。
另外,从DBA_REGISTERED_MVIEWS结构来看,区分远程站点的物化视图是所在站点(GLOBAL_NAME)来区分的,如果两个远程数据库站点名称一样,那么,主数据库是无法区分哪个子站点刷新了哪个没刷新的,就会出现一个站点刷到数据,其余站点刷不到数据的情况。
物化视图相关数据字典
user_mviews all_mviews dba_mviews (物化视图的基本信息及最后刷新信息) user_mview_logs all_mview_logs dba_mview_logs(物化视图日志的信息) user_refresh all_refresh dba_refresh(刷新组信息) user_refresh_children all_refresh_children dba_refresh_children (刷新组成员信息)
参考自yangtingkun的GLOBAL_NAME相同的数据库中物化视图刷新问题(一) ,物化视图注册信息的清除,物化视图日志没有清除等文章,研究这个问题的过程中也搜索并学习了其他人写的东西,最后发现其实yangtingkun都有,并且还挺全,所以这里只列出yangtingkun博客中几篇文章的链接,以后如果要深入研究先仔细看了这几篇再说。