熟悉Oracle的朋友知道,Dataguard是Oracle内置的数据同步工具,也是目前为止做主备最合适的方案。其中Dataguard又分为物理standby和逻辑standby两种,我们平时用的大多数都是物理standby。
在我过往运维过的Oracle Dataguard里,生产环境用逻辑standby的,只用过两个场景,一个是跨版本之间的数据同步,比如一个是11.2.0.4一个是12.1.0.2但这种终究是不推荐;另一个就是滚动升级(Rolling Upgrade),可以实现在不同大版本之间的快速升级。
在使用滚动升级之前,我通常在做大版本升级的时候,都会在新旧生产库之间做一个物理standby,确保两边的数据库是完全一致的。等到升级窗口到来,将standby激活,用dbua或者手动执行升级脚本来完成,等到新的生产环境完成升级检查无误,将应用程序全部切换到新数据库上,旧的根据实际需要决定是下线还是升级到新版本,并升级和旧库做同步的物理standby,完成新库到物理standby之间的dataguard。这样的好处是安全保险,新旧之间的数据库完全一致,即使是新库升级失败也换不会破坏生产环境的配置。缺点也很明显,需要的时间非常长,数据量很大的时候,可能要停机超过一天。无论是业务风险还是对DBA在长时间下的工作挑战都是无法忽视的。
在某一年Oracle技术嘉年华的时候,听一个老外讲起了滚动升级,可以通过逻辑standby完成跨版本的快速升级,这件事情让我眼前一亮,和物理standby升级相比,它的优势非常明显:
- 逻辑standby支持不同大版本之间的数据同步,从11g到12c或者19c,通过逻辑standby可以直接数据同步
- 逻辑standby可以将dbua漫长的时间放在停机窗口之外进行,降低了停机窗口的操作风险
- 大大缩短了停机时间,按照我之前的一个系统升级经验,大概缩短了60%-70%
DB_UNIQUE_NAME: PROD hostname: prod01 版本: 12.1.0.2复制
DB_UNIQUE_NAME: STANDBY hostname: standby01 版本: 12.1.0.2复制
目标库:
DB_UNIQUE_NAME: LOGIC hostname: standby02 版本: 12.1.0.2 -> 19.3.0.0复制
在尽量不动prod01和standby01的配置情况下,完成目标库standby02升级
复制
准备步骤:
1. 停止db broker
如果你配置了db broker,建议在主从节点都关掉
SQL> ALTER SYSTEM SET DG_BROKER_START=FALSE;复制System altered.复制
2.在standby02安装19c
3.在standby02将物理standby切换成逻辑standby
在这一步骤建议先把物理standby做一个RMAN全备份,然后中止主备同步
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL; Database altered.复制
SQL> select name,open_mode,db_unique_name,database_role from v$database; NAME OPEN_MODE DB_UNIQUE_NAME DATABASE_ROLE -------------------- -------------------- ------------------------------ ---------------- PROD MOUNTED LOGIC PHYSICAL STANDBY SQL> ALTER DATABASE RECOVER TO LOGICAL STANDBY KEEP IDENTITY; Database altered.复制SQL> select name,open_mode,db_unique_name,database_role from v$database; NAME OPEN_MODE DB_UNIQUE_NAME DATABASE_ROLE -------------------- -------------------- ------------------------------ ---------------- PROD MOUNTED LOGIC LOGICAL STANDBY复制
开启逻辑standby,检查alert log,是否主备同步正常,一切正常即可准备升级逻辑standby
SQL> ALTER DATABASE OPEN; Database altered.复制SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE; Database altered.复制
4.升级逻辑standby到19.3.0.0
/u01/app/oracle/product/12.1.0/dbhome_1/jdk/bin/java -jar /u01/app/oracle/product/19.0.0/dbhome_1/rdbms/admin/preupgrade.jar FILE DIR /home/oracle/preupgrade ================== PREUPGRADE SUMMARY ================== /home/oracle/preupgrade/preupgrade.log /home/oracle/preupgrade/preupgrade_fixups.sql /home/oracle/preupgrade/postupgrade_fixups.sql Execute fixup scripts as indicated below: Before upgrade: Log into the database and execute the preupgrade fixups @/home/oracle/preupgrade/preupgrade_fixups.sql After the upgrade: Log into the database and execute the postupgrade fixups @/home/oracle/preupgrade/postupgrade_fixups.sql复制
按照提示信息,首先查看一下日志文件,是否有重要信息,尤其是REQUIRED ACTIONS,因为我使用的是一个新安装的单节点库,这里提示的是
REQUIRED ACTIONS ================ None复制
还有一部分是Recommended actions,一般是根据自己实际情况来决定是否执行,其中提示我的有这两个:
EXECUTE DBMS_STATS.GATHER_DICTIONARY_STATS;复制EXECUTE DBMS_STATS.GATHER_FIXED_OBJECTS_STATS;复制
接下来执行preupgrade脚本:
SQL> @/home/oracle/preupgrade/preupgrade_fixups.sql复制
接下来就是用DBUA来升级,当然也可以手动执行各个升级脚本,如果能用图形界面提前export DISPLAY,我还是建议DBUA来做,不会遗漏哪个步骤
$ /u01/app/oracle/product/19.0.0/dbhome_1/bin/dbua复制
完成之后,执行另一个脚本
@/home/oracle/preupgrade/postupgrade_fixups.sql复制
5.升级后检查
检查一下当前版本:
SQL> select name,open_mode,db_unique_name,database_role,version from v$database,v$instance; NAME OPEN_MODE DB_UNIQUE_NAME DATABASE_ROLE VERSION --------- -------------------- ------------------------------ ---------------- ----------------- PROD READ WRITE LOGIC LOGICAL STANDBY 19.0.0.0.0复制
这时候我们看到,版本已经变成了19.3.0.0,接下来检查一下是否有无效对象,对于很多老库可能会比较多,我是新库,所以这里是0
SQL> select count(*) from dba_objects where status='INVALID'; COUNT(*) ---------- 0复制
检查各组件是否已经正常:
SQL> SELECT comp_id,comp_name,version FROM dba_registry;复制
RAC全部都是VALID,单节点除了RAC是option off其他都是VALID,就意味着升级成功了
6.开启主备同步
SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE; Database altered.复制
在日志中查看,主备同步的状态,在强制归档后,两边sequence号需要一致
SQL> select max(sequence#) from v$archived_log;复制
到这一步,滚动升级的所有准备工作就都完成了,接下来我们需要做的是激活逻辑standby为primary
7.激活逻辑standby为primary
到这一步有一个分叉点,到底是用switchover还是failover,我个人比较倾向于用failover,把原来的primary直接shutdown immediate,不要做任何改动,确保一旦需要回退时,把原库直接打开即可。
SQL> ALTER DATABASE ACTIVATE LOGICAL STANDBY DATABASE FINISH APPLY;复制
确认状态:
SQL> select name,open_mode,db_unique_name,database_role,version from v$database,v$instance; NAME OPEN_MODE DB_UNIQUE_NAME DATABASE_ROLE VERSION --------- -------------------- --------------- ---------------- ----------------- PROD READ WRITE LOGIC PRIMARY 19.0.0.0.0复制
建议在这里修改一下db_unique_name,和之前的PROD区分,我改成了PROD_NEW
8.后续工作
到了这一步,我们仍然还需要为新的primary调整一些配置,我仅列出了我到这一步做的操作,更多具体可参考官方文档:https://docs.oracle.com/en/database/oracle/oracle-database/19/sbydb/managing-oracle-data-guard-role-transitions.html
这一步官方文档没有写,但是我建议还是检查一下
SQL> ALTER SYSTEM SET COMPATIBLE = '19.0.0' SCOPE=SPFILE;复制
如果确认没有问题了,那么就按照滚动升级的步骤,搭建新的primary到旧的物理standby之间的逻辑standby,完成滚动升级,旧的primary再保留一阵子,以备不测