迁移后物化视图任务执行报错ORA-23404: 刷新组 "ttd"."xxxx" 不存在

本文讨论了在使用expdp & impdp迁移数据到新库后,遇到定时任务执行失败的问题。通过分析错误日志,发现新环境中物化视图缺失startwith和next子句导致无法创建刷新组,进而引发错误。解决方案包括删除新库中的物化视图并重新创建,同时删除原有的刷新任务以避免重复调度。
今天用expdp&impdp迁移数据到另一个新库
迁移后有个定时任务执行失败如下
Errors in file /oracle/oracle/diag/rdbms/orcl/orcl1/trace/orcl1_j001_3211.trc:
ORA-12012: 自动执行作业 150812 出错
ORA-23404: 刷新组 "ttd"."xxxx" 不存在
ORA-06512: 在 "SYS.DBMS_SYS_ERROR", line 95
ORA-06512: 在 "SYS.DBMS_REFRESH", line 23
ORA-06512: 在 "SYS.DBMS_REFRESH", line 195
ORA-06512: 在 line 1
Wed Oct 22 12:08:45 2014
查询刷新组,发现新环境刷新组不存在,原来环境有
select rowner, rname, job, interval from all_refresh;
对比原来的库的物化视图和新导入库物化视图的定义发现,新导入库中物化视图少了start with 和 next 子句的话,这样就导致没有创建刷新组,由于原来的job中的刷新任务导入到新库中,所以新库在调用dbms_refresh.refresh时报错
但是可以使用exec dbms_mview.refresh('mv');进行刷新
问题解决方法:

删除新库中的物化视图,然后重新创建,同时删除job中的原来的刷新任务,因为再次创建物化视图时会重新创建job如果不删除就会有个定时任务


如下解释:
这个错误还需要从materialized view的创建开始追溯,因为如果在create materialized view语句中加入start with 和 next 子句的话,创建MV的过程中会自动创建一个job,制定定期刷新计划,例如:
create materialized view t1_mv refresh fast 
start with to_date('21-07-2009 17:15:00', 'dd-mm-yyyy hh24:mi:ss') 
  next TRUNC(SYSDATE,'HH')+375/1440
  with primary key 
    as select * from t1;
 
SQL> select job, schema_user, interval, what from all_jobs;
 
       JOB SCHEMA_USER        INTERVAL                            WHAT
---------- ------------------ ----------------------------------- ----------------------------------------------
        21 WANGXIAOQI         TRUNC(SYSDATE,'HH')+375/1440        dbms_refresh.refresh('"WANGXIAOQI"."T1_MV"');
 
SQL>
 可以看到,这个job中的执行内容是:dbms_refresh.refresh('"WANGXIAOQI"."T1_MV"'); 而不是我们普通手动刷新MV时用的 dbms_mview.refresh 。
再来研究一下dbms_refresh这个数据包,这个包是用于产生一个刷新组以方便MV一组为单位统一刷新的。而当MV被制定刷新策略的方式指定时,会自动创建一个刷新组,并将该MV添加至这个刷新组中,所以job可以使用dbms_refresh.refresh来进行刷新。可以来看一下:
 
SQL> select rowner, rname, job, interval from all_refresh where rname = 'T1_MV';
 
ROWNER               RNAME                   JOB INTERVAL
-------------------- ---------------- ---------- ----------------------------------------
WANGXIAOQI           T1_MV                    21 TRUNC(SYSDATE,'HH')+375/1440
 
    再看这个组的成员:
 
SQL> select rowner, rname, job, interval from all_refresh_children where rname = 'T1_MV';
 
ROWNER               RNAME                   JOB INTERVAL
-------------------- ---------------- ---------- ----------------------------------------
WANGXIAOQI           T1_MV                    21 TRUNC(SYSDATE,'HH')+375/1440
 
你遇到的错误: ``` ORA-28827: 传递的密码类型无效 ORA-06512: 在 "SYS.DBMS_CRYPTO_FFI", line 3 ORA-06512: 在 "SYS.DBMS_CRYPTO", line 13 ORA-06512: 在 "OHSAPP.ENCRYPT_MR", line 12 ``` 说明你在使用 `DBMS_CRYPTO.ENCRYPT` 函数时,**密钥格式正确或长度匹配**。 --- ## 🔍 错误分析:ORA-28827: 传递的密码类型无效 ### ✅ 原因 `DBMS_CRYPTO.ENCRYPT` 要求密钥是 `RAW` 类型,并且 **长度必须与算法匹配**: - `AES128` 要求密钥长度为 **16 字节** - `AES192` 要求密钥长度为 **24 字节** - `AES256` 要求密钥长度为 **32 字节** 如果你传入的密钥长度正确,或未正确转换为 `RAW` 类型,就会报这个错误。 --- ## ✅ 正确做法:确保密钥为 RAW 类型且长度正确 ### ✅ 正确的密钥设置方式 ```sql v_key RAW(16) := UTL_RAW.CAST_TO_RAW('fab8materialslot'); ``` ✅ 你设置的是 16 字节密钥,符合 `AES128` 的要求。 但 Oracle 有时对 `UTL_RAW.CAST_TO_RAW` 的结果长度判断准确,建议你使用 `UTL_RAW.SUBSTR` 或 `HEXTORAW` 显式控制长度。 --- ## ✅ 修复后的加密函数 ```sql CREATE OR REPLACE FUNCTION encrypt_mr(p_plain_text IN VARCHAR2) RETURN VARCHAR2 IS v_key RAW(16) := UTL_RAW.CAST_TO_RAW('fab8materialslot'); -- 16字节密钥 v_plain RAW(2000); v_encrypted RAW(2000); BEGIN -- 确保密钥长度为16字节 v_key := UTL_RAW.SUBSTR(v_key, 1, 16); -- 明文转为 RAW v_plain := UTL_RAW.CAST_TO_RAW(p_plain_text); -- 加密(AES128 + ECB + PKCS5Padding) v_encrypted := DBMS_CRYPTO.ENCRYPT( src => v_plain, typ => 256 + 536870912 + 16777216, -- AES128 + ECB + PKCS5 key => v_key ); -- Base64 编码返回 RETURN UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(v_encrypted)); END; / ``` --- ## ✅ 修复后的解密函数 ```sql CREATE OR REPLACE FUNCTION decrypt_mr(p_encrypted_text IN VARCHAR2) RETURN VARCHAR2 IS v_key RAW(16) := UTL_RAW.CAST_TO_RAW('fab8materialslot'); -- 16字节密钥 v_encrypted RAW(2000); v_decrypted RAW(2000); BEGIN -- 确保密钥长度为16字节 v_key := UTL_RAW.SUBSTR(v_key, 1, 16); -- Base64 解码 v_encrypted := UTL_ENCODE.BASE64_DECODE(UTL_RAW.CAST_TO_RAW(p_encrypted_text)); -- 解密 v_decrypted := DBMS_CRYPTO.DECRYPT( src => v_encrypted, typ => 256 + 536870912 + 16777216, -- AES128 + ECB + PKCS5 key => v_key ); -- 返回明文 RETURN UTL_RAW.CAST_TO_VARCHAR2(v_decrypted); END; / ``` --- ## ✅ 验证函数是否有效 ```sql -- 检查函数状态 SELECT OBJECT_NAME, STATUS FROM USER_OBJECTS WHERE OBJECT_NAME IN ('ENCRYPT_MR', 'DECRYPT_MR'); -- 测试加密解密 SELECT encrypt_mr('Hello World') AS encrypted, decrypt_mr(encrypt_mr('Hello World')) AS decrypted FROM dual; ``` --- ## ✅ 总结 | 问题 | 原因 | 解决方法 | |------|------|-----------| | ORA-28827 | 密钥类型或长度错误 | 使用 `RAW(16)`,并用 `SUBSTR` 截断 | | `UTL_RAW.CAST_TO_RAW` | 可能生成长度准确的密钥 | 强制截断为 16 字节 | | `DBMS_CRYPTO.ENCRYPT` | 对密钥要求严格 | 必须使用 RAW 类型和正确长度 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值