Dataguard中pdb的迁移和故障切换

在12c多租户环境中,每一个CDB当中都会有多个pdb在运行,在某些情况下会涉及到CDB之间进行pdb的迁移。当然也就会碰到类似的情况,比如只有其中某一个pdb出现了问题,而其他的pdb都运行正常,这个时候如果对CDB做failover代价太大,这时为了最大程度减少停机时间和缩小影响,我们可以只对这个单独的pdb进行failover或者迁移到同服务器的其他primary cdb。这就需要用到dg broker所带来的新功能,从12.1版本开始,通过dg broker中migrate pluggable database命令能很方便的对pdb进行迁移操作,方便的同时得需要满足一些条件才可以实现,数据库的版本、补丁、COMPATIBLE参数等

实验环境大致如下

Host CDBNAME PDBNAME
Pri ORA12C PDB12C
Pri ORA12C PDB3
Stb ORA12C PDB12C
Stb ORA12C PDB3
Stb CDB1 PDB1

注意事项

下面的步骤假设源CDB库(无论是主库还是备库用来做迁移和failover)和目标CDB库能访问到同一个存储,这样就不需要复制文件操作。

  • 源CDB库可以是RAC也可以是单实例
  • 源CDB的备库不需要是ADG,尽管备库的CDB和PDB都需要被打开为只读模式一段时间
  • 目标CDB可以是RAC也可以是单实例
  • 源端和目标端的存储方式可以是文件系统也可以是ASM
  • 如果是从备库进行迁移,确保之前已经建好了TEMP临时文件
  • 如果源PDB正常关闭:
    • 对于迁移操作,源pdb必须要打开,而且恢复到当前状态否则迁移的过程中会拔下失败
    • 对于failover,源端pdb的正常关闭没什么影响。拔下操作会失败,需要手动清理并完成操作。
    • 如果目标CDB的版本较高,则pdb仍能插入但是处于关闭状态,需要手动进行升级。
    • 无法迁移或者failover到低版本数据库
    • 迁移和failover不支持PDB快照克隆
    • 任务执行完毕以后,需要手动清理主库剩余的数据文件
    • 目标库插入pdb时是通过STANDBYS=NONE的方式,所以在目标库的其他备库中需要手动启用恢复

迁移过程

迁移是用来将PDB从一个cdb迁移到其他cdb中去,migrate命令会将dgbroker配置中主库的pdb拔下,然后插入到另外一个configuration中的主库当中去。

可以将pdb迁移到更高版本的CDB当中去,往低版本则不行。在迁往更高的版本以后,被迁移的pdb在目标cdb中处于关闭状态,你必须执行一些操作来让pdb进行升级。同样pdb可以迁移到更高COMPATIBLE参数值的数据库当中去。

迁移过程的大致步骤如下:

  1. 停止所有连到被迁移pdb的服务
  2. 如果dg环境中你却没有打补丁Patch 25616359 的话,则必须先要停掉备库上所有的pdb,否则redo apply会失败
  3. dgmgrl连接到主库
1
2
$ dgmgrl 
DGMGRL> connect sys as sysdba
  1. 执行migrate命令
1
2
3
4
5
DGMGRL> migrate pluggable database <PDBNAME1> to container <dest-cdb-name> using '/<path>/<DEST_SID>/<PDBNAME1.xml>' connect as <USERNAME>@"<dest-cdb-connect-identifer>";  

-or-

DGMGRL> migrate pluggable database <PDBNAME1> to container <dest-cdb-name> using '/<path>/<DEST_SID>/<PDBNAME1.xml>':

manifest文件存放路径必须可以同时被源端主库和目标端主库访问的到

  1. 当连上目标库以后,migrate命令会做以下事情:
  • 对migrate操作做一些必要的验证工作
  • 从主库拔下pdb
  • 在目标库上使用主库的数据文件通过STANDBYS=NONE的方式创建PDB
  • 如果目标库的版本与源端一样,则在其所有实例中打开PDB
  • 在源端主库中删除pdb,同时删除源端备库中的pdb
  1. 当migrate命令完成以后则执行以下任务:
  • 将之前连接到pdb的服务进行重连
  • 将目标端CDB中的pdb进行备份方便以后恢复
  • 参照Note 1916648.1中开启pdb的备库同步

迁移测试用例

主库pdb的状态

1
2
3
4
5
6
7
8
9
10
11
12
13
sys@ORA12C> show pdbs;

CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB12C READ WRITE NO
4 PDB3 READ WRITE NO

sys@ORA12C> select database_role from v$database;

DATABASE_ROLE
----------------
PRIMARY

生成pdb的xml文件

1
2
3
4
5
6
7
8
9
10
11
sys@ORA12C> alter session set container=pdb3;

Session altered.

BEGIN
DBMS_PDB.DESCRIBE(
pdb_descr_file => '/u01/app/oracle/oradata/pdb3.xml');
END;
/

PL/SQL procedure successfully completed.

在备库机器上连接到源库的dg broker

1
2
3
DGMGRL> connect sys/oracle@ora12c_dg
Connected to "ORA12C_DG"
Connected as SYSDBA.

然后执行迁移命令,使用之前生成的xml文件,因为这里只能使用本地路径,所以必须要是共享目录或者同一个机器上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
DGMGRL> migrate pluggable database immediate pdb3 to container cdb1 using '/u01/app/oracle/oradata/pdb3.xml';
Username: sys@cdb1
Password:
Connected to "cdb1"
Connected as SYSDBA.

Beginning migration of pluggable database PDB3.
Source multitenant container database is ORA12C_DG.
Destination multitenant container database is cdb1.

Connected to "ora12c"
Closing pluggable database PDB3 on all instances of multitenant container database ora12c.
Pluggable database PDB3 on database ORA12C_DG lags its primary
database, ora12c, by 2129 seconds.
Continuing with migration of pluggable database PDB3 to multitenant container database cdb1.
Stopping Redo Apply services on source multitenant container database ORA12C_DG.
Pluggable database description will be written to /u01/app/oracle/oradata/pdb3.xml.
Closing pluggable database PDB3 on all instances of multitenant container database ORA12C_DG.
Disabling media recovery for pluggable database PDB3.
Restarting redo apply services on source multitenant container database ORA12C_DG.
Creating pluggable database PDB3 on multitenant container database cdb1.
Opening pluggable database PDB3 on all instances of multitenant container database cdb1.
Unplugging pluggable database PDB3 from multitenant container database ora12c.
Pluggable database description will be written to /tmp/ora_tfils2PLmU.xml.
Dropping pluggable database PDB3 from multitenant container database ora12c.
Migration of pluggable database PDB3 completed.
Succeeded.

-- 检查目标端cdb的pdb状态
sys@CDB1> show pdbs;

CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB1 MOUNTED
4 PDB3 READ WRITE NO

-- 日志能看到并没有文件的拷贝动作
Completed: create pluggable database PDB3 using '/u01/app/oracle/oradata/pdb3.xml' nocopy standbys=none tempfile reuse
alter pluggable database PDB3 open instances=all
PDB3(4):Autotune of undo retention is turned on.

failover步骤

下面的图展示了将一个故障的pdb迁移到新的cdb过程中初始和结束的状态。

CDB1有三个pdb(PDB1,PDB2,PDB3),同时有一个物理备库。在物理备库同一个机器上有另外一个CDB2,CDB2是可读写状态,出故障的pdb将会迁移到这个CDB上面来。

迁移前的状态:

目前CDB1上的所有pdb都运行正常,CDB1的备库不是处于active dg。CDB2有自己的pdb4

迁移后的状态:

PDB2出现故障,估算需要很长的时间才能恢复,但是目前PDB1和PDB3均允许正常,而且备库的同步也都正常。为了最低程度减小影响,将使用备库pdb2的数据文件去插入到CDB2当中作为读写状态提供给应用访问,然后删除CDB1上的pdb2。这不是一个本机拔插操作,因为它需要一个可读写的CDB。

过程

failover主要用于主库的某个pdb出现了故障,而其他pdbs都允许正常,这时就需要将这个pdb移到其他CDB上去。它提供了一个方法可以只对主库的其中一个pdb进行故障转移而不用影响其他库。备库必须要与目标CDB共享数据文件存放的目录和通过DBMS_PDB.DESCRIBE生成的XML文件所在路径,目标CDB都要能够访问到这些文件,无论是通过在同一台机器或者NFS挂载的方式。

Failover不是一个计划性操作,所以目标就是尽可能降低停机时间。所以要确保一些前提条件:

  • 源和目标库都必须打上相同的补丁包,这样就不用执行额外的脚本,这些内容会在DGMGRL CLI MIGRATE命令时用到,最好的方式是目标CDB与源备库使用同一个oracle home目录
  • 目标CDB最好与源库安装的同样的Oracle组件

failover步骤:

  1. 停掉所有连接到故障pdb主备库的服务
  2. 连接dgmgrl到备库,使用sysdba角色
1
2
$ dgmgrl 
DGMGRL> connect >USERNAME> as sysdba
  1. 在dgmgrl命令行中执行failover操作。Note:这里的操作与之前的迁移命令一模一样
1
2
3
DGMGRL> migrate pluggable database <PDBNAME1> to container <dest-cdb-name> using '/<path>/<PDBNAME1>/<PDBNAME1.xml>' connect as <USERNAME>@"<dest-cdb-connect-identifer>";
-or-
DGMGRL> migrate pluggable database <PDBNAME1> to container <dest-cdb-name> using '/<path>/<PDBNAME1>/<PDBNAME1.xml>': # This will prompt for user name and password
  1. 当到目标CDB的连接建立以后,主要做了如下事情:
    1. 做了很多failover操作必要的校验
    2. 如果备库的redo apply运行则会停掉
    3. 将所有备库实例打开到read only状态
    4. 根据迁移命令指定的路径通过DBMS_PDB.DESCRIBE创建XML文件
    5. 停止源备库PDB的恢复
    6. 如果源备库本身不是ADG状态则还原成mount
    7. 通过备库的数据文件(NOCOPY)在目标CDB创建PDB,使用STANDBYS=NONE选项
    8. 在目标CDB的所有实例打开PDB
    9. 拔掉源主库的PDB,如果操作有报错则需要手动解决
    10. 如果拔下操作顺利,则通过KEEP DATAFILES的方式删掉PDB,这同样会删除所有源备库的pdb。
  2. 如果都顺利结束,则将之前的服务都连到新PDB上来

  3. 备份目标CDB的PDB允许恢复
  4. 开启目标CDB所有备库的恢复操作

因为Failover过程中使用的DGMGRL命令与之前迁移操作的基本一样,这里就不再一一赘述,全文完。