1. 问题简述
执行 impdp 时报 ORA-39405
错误。
2. 报错信息
2.1. 报错内容
ORA-39002: invalid operation
ORA-39405: Oracle Data Pump does not support importing from a source database with TSTZ version 36 into a target database with TSTZ version 32.
2.2. 报错截图
3. 问题分析
3.1. 错误解释
[oracle@dbtest ~]$ oerr ora 39405
39405, 00000, "Oracle Data Pump does not support importing from a source database with TSTZ version %s into a target database with TSTZ version %s."
// *Cause: The source database was at a different time zone version than the
// target database and there were tables that contained TIMESTAMP
// WITH TIME ZONE (TSTZ) data.
// *Action: Convert the target database to the same time zone version or
// later as the source database or use Oracle Data Pump with
// conventional data movement to export then import this data.
3.2. 分析问题
这个错误是因为数据库时区版本不一致造成的,并且是源数据时区版本高,目标数据库时区版本低。
4. 问题解决
安装时区补丁29997937,具体步骤如下:
4.1. 下载最新的 OPatch 和 DSTV36 更新补丁
-
Opatch Version Patch:
https://updates.oracle.com/download/6880880.html
下载的文件名:p6880880_190000_Linux-x86-64.zip -
DST V36 Patch:
https://updates.oracle.com/download/32327201.html
下载的文件名:p32327201_190000_Linux-x86-64.zip
4.2. 升级Opatch版本
将下载好的文件拷贝到Oracle用户的根目录下,并修改文件权限让oracle可执行,然后切换到Oracle用户,执行下列操作。
# 检查当前 OPatch 的版本
~]$ $ORACLE_HOME/OPatch/opatch version
OPatch Version: 12.2.0.1.17
OPatch succeeded.
# 备份当前 OPatch 目录
~]$ mv $ORACLE_HOME/OPatch $ORACLE_HOME/OPatch_bak
# 解压最新的 OPatch 到 ORACLE_HOME 目录
~]$ unzip p6880880_190000_Linux-x86-64.zip -d $ORACLE_HOME/
..... # 这里省略解压的内容
# 检查更新后 OPatch 的版本
~]$ $ORACLE_HOME/OPatch/opatch version
OPatch Version: 12.2.0.1.35
OPatch succeeded.
4.3. Patch应用前确认 TZ_VERSION 的版本
登录到Oracle数据库,执行下列操作。
SQL> select tz_version from registry$database;
TZ_VERSION
----------
32
SQL> SELECT DBMS_DST.get_latest_timezone_version FROM dual;
GET_LATEST_TIMEZONE_VERSION
---------------------------
32
4.4. 将 DSTV36 更新补丁应用到 ORACLE HOME
将下载好的文件拷贝到Oracle用户的根目录下,并修改文件权限让oracle可执行,然后切换到Oracle用户,执行下列操作。
# 解压文件
~]$ unzip p32327201_210000_Linux-x86-64.zip
..... # 这里省略解压的内容
# 预检查升级
~]$ $ORACLE_HOME/OPatch/opatch prereq CheckConflictAgainstOHWithDetail -ph ~/32327201/
将补丁应用到 ORACLE_HOME 目录下:
# 进入补丁目录
~]$ cd ./32327201/
~]$ $ORACLE_HOME/OPatch/opatch apply -oh $ORACLE_HOME/
~]$ $ORACLE_HOME/OPatch/opatch lsinv | grep -i "DSTV36 UPDATE"
4.5. 查看下载的TZ版本
SQL> SELECT DBMS_DST.get_latest_timezone_version FROM dual;
4.6. Upgrade mode下启动数据库
SQL>
-- 关闭数据库
shutdown immediate;
-- 启动数据库到升级模式
startup upgrade;
-- 查询数据库与实例状态
SELECT name, open_mode FROM v$database;
SELECT instance_name, status FROM v$instance;
4.7. 升级前准备
SQL>
DECLARE
l_tz_version PLS_INTEGER;
BEGIN
l_tz_version := DBMS_DST.get_latest_timezone_version;
DBMS_OUTPUT.put_line('l_tz_version=' || l_tz_version);
DBMS_DST.begin_prepare(l_tz_version);
END;
/
SQL>
COLUMN property_name FORMAT A30
COLUMN property_value FORMAT A20
SELECT property_name, property_value
FROM database_properties
WHERE property_name LIKE 'DST_%'
ORDER BY property_name;
4.8. 查找受影响的表
SQL>
EXEC DBMS_DST.find_affected_tables;
SELECT COUNT(*) FROM sys.dst$affected_tables;
SELECT * FROM sys.dst$error_table;
4.9. 结束升级前准备
SQL>
EXEC DBMS_DST.end_prepare;
4.10. 开始升级TZ
SQL>
SET SERVEROUTPUT ON
DECLARE
l_tz_version PLS_INTEGER;
BEGIN
SELECT DBMS_DST.get_latest_timezone_version
INTO l_tz_version
FROM dual;
DBMS_OUTPUT.put_line('l_tz_version=' || l_tz_version);
DBMS_DST.begin_upgrade(l_tz_version);
END;
/
如果是容器数据库,那么各个PDB也需要升级,我暂时不知道如何一次升级所有的PDB
4.11. 关闭升级模式,正常启动数据库
SQL>
shut immediate;
startup;
4.12. 结束升级
SQL>
SET SERVEROUTPUT ON
DECLARE
l_failures PLS_INTEGER;
BEGIN
DBMS_DST.upgrade_database(l_failures);
DBMS_OUTPUT.put_line('DBMS_DST.upgrade_database : l_failures=' || l_failures);
DBMS_DST.end_upgrade(l_failures);
DBMS_OUTPUT.put_line('DBMS_DST.end_upgrade : l_failures=' || l_failures);
END;
/
4.13. 查看升级结果
SQL>
COLUMN property_name FORMAT A30
COLUMN property_value FORMAT A20
SELECT property_name, property_value
FROM database_properties
WHERE property_name LIKE 'DST_%'
ORDER BY property_name;
5. 问题总结
6. 其他拓展知识
附录
附录A. 相关联的文章
附录B. 参考
附录C. 执行 opatch 时报错的处理
1)opatch lsinventory 报oraInst.loc文件不存在
拷贝 oraInst.loc 文件到 ORACLE HOME 目录
~]$ cp /etc/oraInst.loc $ORACLE_HOME/
2)PrereqSession failed: RawInventory gets null OracleHomeInfo
解决办法:
切换到ORACLE_HOME目录并将其附加到oraInventory中
~]$ cd $ORACLE_HOME/oui/bin
~]$ ./attachHome.sh
如果执行上述命令又如下错误:
You do not have sufficient permissions to access the inventory '/u01/app/oraInventory'. Installation cannot continue. It is required that the primary group of the install user is same as the inventory owner group. Make sure that the install user is part of the inventory owner group and restart the installer.
3)Permission denied on /u01/app/oraInventory
即Oracle用户没有权限修改/u01/app/oraInventory
中的文件,可切换到grid
用户下,执行修改oraInventory的目录权限,让同组(相同oinstall组)的用户可修改和执行该文件。
~]$ chmod -R g+wx /u01/app/oraInventory
3)使用命令 /opatch lsinventory
显示在中央清单中注册的所有OracleHome的补丁情况。