写这个自动产生同步脚本的代码足足用了我两天的时间,今天上午终于做完了。
我这里说一下我处理这个问题的思路:
现在要做的是ipra开发环境ipradev的用户ipra、mas和ipra国航测试环境caipratest的用户caipra、camas之间的DDL同步。注意这里是不同数据库下不同schema间的DDL同步,并且这些schema下的default tablespace和索引所在的tablespace均不相同。
我原先本来用streams已经实现了上述DDL同步,但是因为streams不够稳定,我决定放弃streams,转而用代码来自动产生同步脚本。
生成这个同步脚本的思路是:
1、比较两边数据库相对应schema下同名object的last_ddl_time,以ipradev为同步的源头,去同步那些在caipratest上last_ddl_time滞后的object。
2、如果ipradev中有object,但在caipratest中并不存在同名object,则在caipratest中建立该object。
3、如果caipratest中有object,但在ipradev中并不存在同名object,则在caipratest中drop该object。
在写上述代码的时候考虑到了如下问题:
1、考虑到了table、constraint、table中的字段的default值、table comment、column comment、index、view、sequence、type、type body、function、package、package body、procedure和trigger间的同步。
2、考虑到了按指定的"表空间映射"生成的DDL脚本中的表空间转换。
3、不支持synonym的同步、因为synonym的目标可能是不同的schema,这个schema间的转换我无法事前知道,synonym的同步就手工做一下好了。
4、dbms_metadata.get_ddl的返回值是CLOB,我专门写了一个子存储过程来一行一行打印CLOB。
5、dbms_output.put_line打印行的时候有一个不能超过255个byte的限制,如果你要print 的行的长度超过255个byte,oracle这里会报错 ORA-06502: PL/SQL numeric or value error: host bind array too small,在我代码里专门对这种情况做了处理,并且考虑到了中文,这个里面为了保证print出来的代码能够顺利的在目标数据库执行,并没有生硬的从254处截断。
6、oracle里server output的最大长度是100万,如果你一次更新需要print的内容太多,会超过这个100万的限制,此时oracle会报错:ORA-20000: ORU-10027: buffer overflow, limit of 1000000 bytes,出现这种情况的时候需要手工处理一下。
P_SYS_GEN_DIFF_DEV_AND_TEST.prc是自动产生同步脚本的主存储过程
P_SYS_PRINT_DDL.prc是专门处理CLOB的子存储过程
Leave a comment