背景
某项目需要对生产环境数据库进行数据迁移,需要迁移的数据库版本为12.2.0.1.0
RAC双节点,目标数据库为单实例数据库,版本一样。简单一句话就是,需要将数据从rac迁移到单机。
方案
本次尝试过以下三种方案
- 通过rman进行备份迁移,但因为rac数据库和单机数据库控制文件spfile存在差异,需要手动修改的地方较多,在迁移过程中并不顺利,考虑到数据的一致性,最后放弃该方案。方案可以参考Steps to restore from RAC to Single Instance (RMAN)
- 通过expdp和impdp数据泵方式进行迁移,方案可以参考Oracle 12c pdb使用expdp/impdp导入导出,impdp导入时出现较多错误,错误都集中其中一个schema上,最后单独对该schema进行导入,但因为错误太多不排除其他schema出现错误,也是考虑到数据的完整性,最后虽然成功导入但还是放弃该方案。
- 通过oracle 12c新特性克隆远程数据库的方案对数据进行迁移,cdb和pdb是oracle 12c的一个新特性,允许oracle数据库以多租户多实例方式运行,每个用户可以分配一个cdb(相当于一台数据库主机),每个cdb可以创建多个pdb(pluggable database,可插拔数据库),不同数据库之间pdb可以克隆。
实现
下文远程数据库指的是需要迁移的远程数据库,本地数据库指的是迁入的数据库
- 在远程数据库上创建用户,本地数据库将通过该用户创建dblink进行克隆
[oracle@Portal-DB-Node02 ~]$ sqlplus / as sysdba SQL*Plus: Release 12.2.0.1.0 Production on Wed Jun 24 10:10:47 2020 Copyright (c) 1982, 2016, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production SQL> show pdbs CON_ID CON_NAME OPEN MODE RESTRICTED ---------- ------------------------------ ---------- ---------- 2 PDB$SEED READ ONLY NO 3 PORTALPROD MOUNTED SQL> alter session set container=PORTALPROD; Session altered. SQL> CREATE USER cloner IDENTIFIED BY oracle; User created. SQL> GRANT CREATE SESSION, CREATE PLUGGABLE DATABASE TO cloner; Grant succeeded.
- 本地数据库新建连接描述符,修改tnsnames.ora
tnsnames.ora文件位于$ORACLE_HOME/network/admin
目录下,如/u01/app/oracle/product/12.2.0/dbhome_1/network/admin
,如果目录下没有该文件就手动创建一个,向该文件添加远程数据库的连接(oracle用户)
PORTALPROD = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 172.16.11.2)(PORT = 1539)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = PORTALPROD) ) )
克隆数据库可以通过cdb连接克隆也可以直接连pdb进行克隆,两种方式都尝试过,在通过cdb连接克隆时出现ORA-01435错误无法解决因此改为pdb
- 本地数据库创建dblink
[oracle@Portal-DB03 admin]$ sqlplus / as sysdba SQL*Plus: Release 12.2.0.1.0 Production on Wed Jun 24 10:25:08 2020 Copyright (c) 1982, 2016, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production SQL> drop database link xlLink; Database link dropped. SQL> create database link xlLink connect to cloner identified by oracle using 'PORTALPROD'; Database link created. SQL> desc user_tables@xlLink;
如果desc user_tables@xlLink能正常返回说明连接正常
- 将远程数据修改为只读模式
[oracle@Portal-DB-Node02 ~]$ sqlplus / as sysdba SQL*Plus: Release 12.2.0.1.0 Production on Wed Jun 24 10:35:22 2020 Copyright (c) 1982, 2016, Oracle. All rights reserved. Connected to: Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production SQL> alter pluggable database PORTALPROD close; Pluggable database altered. SQL> alter pluggable database PORTALPROD open read only; Pluggable database altered.
如果alter pluggable database PORTALPROD close;
长时间未响应,可以直接进入数据库执行shutdown
命令,效果是一样的
SQL> alter session=PORTALPROD SQL> shutdown immediate;
- 本地数据库执行clone命令
SQL> create pluggable database PORTALPROD from PORTALPROD@xlLink file_name_convert=('+DATA/PORTALDB/','/u01/app/oracle/oradata/PORTALPROD/'); Pluggable database created.
该命令格式为
create pluggable database {本地数据库名称} from {远程数据库名称}@{远程数据库dbLink} file_name_convert=('{远程数据库需要替换的文件前缀}','{替换成本地数据库的文件前缀}');
- 本地数据库名称:就是你创建的本地数据库名称,尽量和远程保持一直,这样通过修改dns可以做到应用连接信息无需修改。
- 远程数据库名称:需要迁移的远程数据库名称,可以通过
show pdbs
命令查看
SQL> show pdbs; CON_ID CON_NAME OPEN MODE RESTRICTED ---------- ------------------------------ ---------- ---------- 2 PDB$SEED READ ONLY NO 3 PORTALPROD READ ONLY NO
- file_name_convert:不同数据库之间可能安装的目录不一样,导致数据文件存储的位置不一样,比如远程服务器数据文件存储在
/home/oracle/oradata
下,但本地数据库没有这个目录,本地数据库数据文件存储在/u01/oracle/oradata
目录下,这时候就要做一下文件名的转换,其实就是把datafile里的路径字符串替换。在rac中,数据文件是存放在ASM中的,所以你看到的路径应该是长这样的
SQL> select file_name from dba_data_files; FILE_NAME -------------------------------------------------------------------------------- +DATA/PORTALDB/9A6B07BC35FC2743E0530101007F1BF5/DATAFILE/system.274.1027852675 +DATA/PORTALDB/9A6B07BC35FC2743E0530101007F1BF5/DATAFILE/sysaux.275.1027852675 +DATA/PORTALDB/9A6B07BC35FC2743E0530101007F1BF5/DATAFILE/undotbs1.273.1027852675 +DATA/PORTALDB/9A6B07BC35FC2743E0530101007F1BF5/DATAFILE/undo_2.277.1027852725 +DATA/PORTALDB/9A6B07BC35FC2743E0530101007F1BF5/DATAFILE/users.278.1027852727 .....
前面是+DATA
作为前缀,这个在本地数据库使用本地硬盘作为存储介质肯定是不行的,本地数据库是长这样的
SQL> select file_name from dba_data_files; FILE_NAME -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /home/oracle/app/oracle/oradata/PORTALPROD/9A6B07BC35FC2743E0530101007F1BF5/DATAFILE/system.274.1027852675 /home/oracle/app/oracle/oradata/PORTALPROD/9A6B07BC35FC2743E0530101007F1BF5/DATAFILE/sysaux.275.1027852675 /home/oracle/app/oracle/oradata/PORTALPROD/9A6B07BC35FC2743E0530101007F1BF5/DATAFILE/undotbs1.273.1027852675 /home/oracle/app/oracle/oradata/PORTALPROD/9A6B07BC35FC2743E0530101007F1BF5/DATAFILE/undo_2.277.1027852725 ....
因此file_name_convert可以这么写
file_name_convert('+DATA','希望存放的路径');
也可以这么写
file_name_convert('+DATA/PORTALDB','希望存放的路径');
总之要把+DATA替换成真实的路径
- 启动本地数据库
克隆完毕后,本地数据库处于MOUNTED
状态,需要将其打开
SQL> alter pluggable database PORTALPROD open; SQL> show pdbs CON_ID CON_NAME OPEN MODE RESTRICTED ---------- ------------------------------ ---------- ---------- 2 PDB$SEED READ ONLY NO 6 PORTALPROD READ WRITE NO
如果状态是OPEN WRITE
就是正常的。
- 配置连接
创建新的pdb,需要手动添加pdb的监听,不然客户端无法连接到pdb(oracle 12c应该有自动添加监听的办法,没找到),编辑$ORACLE_HOME/network/admin/listener.ora
(如/u01/app/oracle/product/12.2.0/dbhome_1/network/admin/listener.ora)文件,增加以下配置
SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = PORTALDB) (ORACLE_HOME = /u01/app/oracle/product/12.2.0/dbhome_1) (GLOBAL_DBNAME = PORTALDB.XXXX) ) (SID_DESC= (SID_NAME=PORTALDB) (ORACLE_HOME = /home/oracle/app/oracle/product/12.2.0/dbhome_1) (GLOBAL_DBNAME=portalprod.XXXX) ) )
SID_LIST_LISTENER定义了监听列表,你需要手动增加一个监听项
(SID_DESC= (SID_NAME=PORTALDB) (ORACLE_HOME = /home/oracle/app/oracle/product/12.2.0/dbhome_1) (GLOBAL_DBNAME=portalprod.XXXX) )
GLOBAL_DBNAME需要带上domain,domain的名称参考默认的那个就行,如果不知道也可以通过语句进行查询
SQL> select * from global_name; GLOBAL_NAME -------------------------------------------------------------------------------- PORTALDB.XXXX
XXXX就是domain的名称
本地tnsnames.ora参考如下:
PORTALPROD = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 172.16.11.6)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = portalprod.xlzd) ) )
碰到的问题
- 无法创建文件问题
在执行clone的过程中,出现一个无法创建TEMPFILE
的问题(忘记保留现场了),解决办法就是,执行完create pluggable database命令,就到指定目录下手动创建TEMPFILE
目录,应该是一个权限的问题。如果克隆过程报错导致克隆中断,再次克隆需要删除数据库重新来过。
SQL> drop pluggable database PORTALPROD including datafiles;
并且删除已经生成好的部分文件,就是file_name_convert指定的路径下文件。
- 迁移结束后客户端无法连接到数据库,报
ORA-01017 Invalid Username/Password; Logon Denied
用户名密码错误,但后台通过sqlplus都能正常登录,后面通过修改监听的名称从SERVICE_NAME = PORTALPROD
修改为SERVICE_NAME = PORTALPROD.XXXX)
加上domain后解决。(oracle的SERVICE_NAME一直很迷,有时候需要加domain有时候不需要,总之碰到问题两边都试试)
no comment untill now