背景

某项目需要对生产环境数据库进行数据迁移,需要迁移的数据库版本为12.2.0.1.0RAC双节点,目标数据库为单实例数据库,版本一样。简单一句话就是,需要将数据从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有时候不需要,总之碰到问题两边都试试)

参考

,
Trackback

no comment untill now

Add your comment now