久疏战阵,这不拖雷休假去了我一上去干活就犯了几个错误,吸取一下教训,还真发现了有些东西自己不知道的,这错犯得,值!
说起来昨天也很奇怪,因为一个crm库的mview刷新放到了crontab而不是job里面去执行,所以监控系统忘了监控mview刷新是否成功。等到昨天晚上发现crm库的归档目录使用率达到90%以上,进去一看发现几乎1分钟产生一个归档日志,平时crm这个时候估计半小时才能产生一个日志,究竟为什么呢,登陆数据库看了一下当前active的session,发现有一个program列为sqlplus的session一直在活动,根据sql_hash_value来查一下发现是mview刷新的语句,退出sqlplus去看crontab的日志,发现其中一个mview刷新居然一直失败
BEGIN dbms_mview.refresh(’CRM2.MV_BMW_USERS_DB1′); END;
*
ERROR at line 1:
ORA-12008: error in materialized view refresh path
ORA-00001: unique constraint (CRM2.UK_MV_BMW_USERS_NICK1) violated
ORA-06512: at “SYS.DBMS_SNAPSHOT”, line 803
ORA-06512: at “SYS.DBMS_SNAPSHOT”, line 860
ORA-06512: at “SYS.DBMS_SNAPSHOT”, line 841
ORA-06512: at line 1
居然有唯一冲突,master table和mview都建立了unique constraint,但是居然出现了唯一冲突(产生的原因现在未明,将在下一篇blog里面去模拟),当时想到了2种方法,一种是直接做一个complete refresh,另外一种是找到重复的记录进行删除。当时自作聪明得以为后一种方法比较方便快捷,所以就开始了我的错误之旅。
首先去创建了exceptions表,然后disable UK_MV_BMW_USERS_NICK1
alter table MV_BMW_USERS_DB1 disable constraint UK_MV_BMW_USERS_NICK1;
然后exec dbms_mview.refresh(’CRM2.MV_BMW_USERS_DB1′);
然后alter table MV_BMW_USERS_DB1 enable constraint UK_MV_BMW_USERS_NICK1 exceptions into exceptions;
再从exceptions表里找出重复的数据
select nick,id from MV_BMW_USERS_DB1 where rowid in (select row_id from exceptions);
找到2条重复数据,删除之,第一个错误开始了
delete from MV_BMW_USERS_DB1 where id=’39f9cd610eea28acca1c2934324253c8′;
ERROR at line 1:
ORA-01732: data manipulation operation not legal on this view
居然忘了mview上不能做dml,该死,数据都刷过来了,这下清除不掉就麻烦了
要不先用novalidate把约束起来吧
alter table MV_BMW_USERS_DB1 enable novalidate constraint UK_MV_BMW_USERS_NICK1;
当场失败!
又一个错误!居然忘了novalidate不是这么用的,由于这个constraint先建index再加约束的,所以
直接enable novalidate是不行的。
既然这也行不通那只有删除mview定义,然后在表上删除重复数据了
由于master表也是个mview,先到master site把master mview的刷新job停下来,保证master mview的mv log 不再增加,然后在mview site这边删除mv定义,然后删除重复记录,然后再建mv定义,然后增量刷新就可以了。但是在这里又犯了一个错误!
我用dbms_job.broken(jobnumber,true)来停止了那个job,但是没有commit,这时候虽然刷新job被阻止在job$ lock上不会继续刷新,但是由于没commit,当退出sqlplus窗口的时候这个job的broken又将变成N,原来被阻止的刷新job将会把新增加的记录刷过来。这里犯的错误就是运行dbms_job.broken没有做全局性修改。这样的当我在mview site重建mv定义时实际上master site里面的mview log是有记录的,当重建mview后,mview log里面的记录全部被清空,所以这时候会产生两边数据不一致,也就产生了数据丢失。
事情到了这一步,只能全刷新了,由于原来提供给应用访问的是基于mview上建立的一个视图,所以暂时把视图通过数据链路建立到远程的表上,然后对mview进行全刷新,然后再重建视图定义。
总结一下,做事情以前没想清楚,以为找到方便的方法,但是做的时候太粗心,其实早把视图建到远程表上进行全刷新是最方便的,自做聪明而且没做好真是该好好反省一下。
此文说的是我亲身经历,但是由于当时环境过于复杂,所以文章里面讲述不是太清楚,可能会看的糊里糊涂不知道我在说什么,总之我想强调的,不管是谁,如果粗心大意,自做聪明,肯定是会犯错的。希望大家别像我一样犯错!
0 Responses to “久疏战阵,犯下的几个错误”