Oracle19c DataGuard

article/2025/9/29 16:07:37

为记录的更详细点,文章经过二次编辑,有几张图的时间对不上,不过不影响查阅。

CSDN排版不太友好,有些代码的进位都给省略了。

文章早就编辑好了,由于一些原因一直没发出来。

根据自己的环境,一定要仔细比对db_name、db_unique_name、文件路径等等。

文章如有遗漏或错误,欢迎指正。🤝

环境概况

主机一:h1.e.cc

主机二:h2.e.cc

我这里先是在 主机一 上创建了一个 CDB 数据库:DB0

图个方便,把sys密码设置成了0.

初步搭建完成后:

主库:db_name 是 DB0, db_unique_name 是 DB1.

备库:db_name 是 DB0, db_unique_name 是 DB2.


网络

DataGuard 环境得配置静态监听,注意加粗及高亮部分,listener文件中不能有制表符(tab)

主库添加:

SID_LIST_LISTENER=

(SID_LIST= (SID_DESC= (GLOBAL_DBNAME=DB1.e.cc)(SID_NAME=DB0)

(ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1)))

备库添加:

SID_LIST_LISTENER=

(SID_LIST= (SID_DESC= (GLOBAL_DBNAME=DB2.e.cc)(SID_NAME=DB0)

(ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1)))

记得检查两边监听,都要处于启动状态。


tnsnames.ora文件中添加:(主备库都要添加)

DB1 = (DESCRIPTION =

(ADDRESS = (PROTOCOL = TCP)(HOST = h1.e.cc)(PORT = 1521))

(CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = DB1.e.cc)))

DB2 =(DESCRIPTION =

(ADDRESS = (PROTOCOL = TCP)(HOST = h2.e.cc)(PORT = 1521))

(CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = DB2.e.cc)))


注:$ORACLE_HOME/sqlplus/admin/glogin.sql 里添加了一行:

set sqlp "_user '@'_connect_identifier >>> "

~oracle/.bash_profile 里 ORACLE_SID=DB0

所以,当看到:SYS@DB0 >>> 时,说明我是通过 OS 验证方式连接实例的。

像这样: sqlplus / as sysdba

而看到:

SYS@DB1>>> 或 SYS@DB2 >>> 时,说明我是通过监听连接实例的。

像这样: sqlplus sys/0@DB1 as sysdba

或 sqlplus sys/0@DB2 as sysdba


主机一(主库):

要处于归档模式:

查看:archive log list;

如果没有启用归档模式,数据库要 mount 状态执行:

alter database archivelog;

standby log

查看redo概况:

select bytes/1024/1024 from v$log 
where group# in (select group# from v$logfile);

创建(redo member 数+1)个 standbylog。

alter database add standby logfile '/u01/app/oracle/oradata/DB0/standby01.log' size 200M;
alter database add standby logfile '/u01/app/oracle/oradata/DB0/standby02.log' size 200M;
alter database add standby logfile '/u01/app/oracle/oradata/DB0/standby03.log' size 200M;
alter database add standby logfile '/u01/app/oracle/oradata/DB0/standby04.log' size 200M;

开启强写日志

alter database force logging;

关闭闪回

alter database flashback off;

local_listener 要设置为空

alter system set local_listener='';

从当前spfile创建一个pfile

create pfile from spfile;

关闭数据库

shu immediate;

编辑数据库参数文件pfile

注意高亮及加粗部分。

DB0.__data_transfer_cache_size=0

DB0.__db_cache_size=1828716544

DB0.__inmemory_ext_roarea=0

DB0.__inmemory_ext_rwarea=0

DB0.__java_pool_size=0

DB0.__large_pool_size=16777216

DB0.__oracle_base='/u01/app/oracle'

DB0.__pga_aggregate_target=838860800

DB0.__sga_target=2516582400

DB0.__shared_io_pool_size=134217728

DB0.__shared_pool_size=520093696

DB0.__streams_pool_size=0

DB0.__unified_pga_pool_size=0

*.audit_file_dest='/u01/app/oracle/admin/DB0/adump'

*.audit_trail='db'

*.compatible='19.0.0'

*.control_files='/u01/app/oracle/oradata/DB0/control01.ctl'

*.db_block_size=8192

*.db_domain='e.cc'

*.db_name='DB0'

*.db_recovery_file_dest='/u01/app/oracle/fast_recovery_area'

*.db_recovery_file_dest_size=20g

*.diagnostic_dest='/u01/app/oracle'

*.dispatchers='(PROTOCOL=TCP) (SERVICE=DB0XDB)'

*.enable_pluggable_database=true

*.local_listener=''

*.log_archive_format='%t_%s_%r.dbf'

*.nls_language='AMERICAN'

*.nls_territory='AMERICA'

*.open_cursors=300

*.pga_aggregate_target=798m

*.processes=320

*.remote_login_passwordfile='EXCLUSIVE'

*.sga_target=2394m

*.undo_tablespace='UNDOTBS1'

-- 以下是新加的参数

DB_UNIQUE_NAME=DB1

LOG_ARCHIVE_CONFIG='DG_CONFIG=(DB1,DB2)'

LOG_ARCHIVE_DEST_1=

'LOCATION=/u01/app/oracle/fast_recovery_area

VALID_FOR=(ALL_LOGFILES,ALL_ROLES)

DB_UNIQUE_NAME=DB1'

LOG_ARCHIVE_DEST_2=

'SERVICE=DB2 SYNC AFFIRM

VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)

DB_UNIQUE_NAME=DB2'

FAL_SERVER=DB2

DB_FILE_NAME_CONVERT='/DB2/','/DB1/'

LOG_FILE_NAME_CONVERT='/DB2/','/DB1/'

STANDBY_FILE_MANAGEMENT=AUTO

rm或mv之前的 spfile.

rm -f spfileDB0.ora

创建spfile,并启动数据库实例

登录 sqlplus, 创建 spfile. 再 startup.

create spfile from pfile;

查看:

可以看到 BD_UNIQUE_NAME 变成 DB1 了,之前是 DB0.

准备配置备库

#未能正常启动就回去看看哪里疏漏了什么细节。
#如果可以正常开启数据库就把 pfile 和密码文件复制到备库上, 准备编辑备库的参数文件
cd $ORACLE_HOME/dbs
scp initDB0.ora h2:/u01/app/oracle/product/19.0.0/dbhome_1/dbs/
scp orapwDB0 h2:/u01/app/oracle/product/19.0.0/dbhome_1/dbs/

主机二(备库)

编辑备库参数文件

到主机二$ORACLE_HOME/dbs目录编辑参数文件

//互换DB1和DB2。
sed -i 's/DB1/AAAA/g' initDB0.ora
sed -i 's/DB2/DB1/g' initDB0.ora
sed -i 's/AAAA/DB2/g' initDB0.ora

执行上面三条替换命令,DB1DB2 就互换过来了:

DB_UNIQUE_NAME=DB2

LOG_ARCHIVE_CONFIG='DG_CONFIG=(DB2,DB1)'

LOG_ARCHIVE_DEST_1=

'LOCATION=/u01/app/oracle/fast_recovery_area

VALID_FOR=(ALL_LOGFILES,ALL_ROLES)

DB_UNIQUE_NAME=DB2'

LOG_ARCHIVE_DEST_2=

'SERVICE=DB1 SYNC AFFIRM

VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)

DB_UNIQUE_NAME=DB1'

FAL_SERVER=DB1

DB_FILE_NAME_CONVERT='/DB1/','/DB2/'

LOG_FILE_NAME_CONVERT='/DB1/','/DB2/'

STANDBY_FILE_MANAGEMENT=AUTO

创建目录

创建好需要的目录:

#根据自己的环境,仔细比对是否正确
mkdir -p /u01/app/oracle/admin/DB0/adump 
mkdir -p /u01/app/oracle/oradata/DB0/ 
mkdir -p /u01/app/oracle/fast_recovery_area

开启备库到nomount状态

创建spfile:

create spfile from pfile;

开启备库到nomount状态

startup nomount;

rman复制

duplicate target database for standby from active database nofilenamecheck;

不出意外的话,能看到这么一行:

如有报错,看看报错信息,回去看看哪里搞错了,删除生成的"问题文件",再尝试能否成功。

到sqlplus查看:

select name,db_unique_name,database_role,open_mode from v$database;

database_role 为 PHYSICAL STANDBY,duplicate 操作完成后就会启动到 mount 状态。

开始同步(应用日志)

备库进sqlplus,应用日志

recover managed standby database using current logfile disconnect;

可以看到,open_mode 为 read only with apply.

取消应用:

recover managed standby database cancel;

取消应用日志后,就变成 read only 了。

完成基本搭建了

基本管理

temp_undo

最好开启 temp_undo:

alter system set temp_undo_enabled=true;

dg_broker

alter system set dg_broker_start=true;

reset log_archive_dest_n

alter system reset log_archive_dest_1 scope=spfile;
alter system reset log_archive_dest_2 scope=spfile;

然后重启两个数据库。都开启到 read write 状态。

开启闪回

alter database flashback on;

dgmgrl

到 dgmgrl 里做一些骚操作吧!

dgmgrl sys/0@DB1

注:这里先连到主库。

新建一个配置

新建一个配置,就叫 dgtest 吧。

create configuration dgtest as primary database is 'DB1' connect identifier is 'DB1';
add database 'DB2' as connect identifier is 'DB2';

查看

show configuration; 

还未开启。

show database verbose 'DB1';
show database verbose 'DB2';

两个都是 disable 状态。

启用

enable configuration; 
enable database 'DB1';
enable database 'DB2';

查看

show database verbose 'DB1';
show database verbose 'DB2';
show configuration;

没有报错,也没有警告。 就很舒服。

#注:有些状态内容是一分钟刷新一次的,所以做完更改可能要稍微等一会才能看到变化。

做一些改动

edit database 'DB1' set property FastStartFailoverTarget='DB2';

edit database 'DB2' set property FastStartFailoverTarget='DB1';

edit database 'DB1' set property LogXptMode='SYNC';

edit database 'DB2' set property LogXptMode='SYNC';

EDIT CONFIGURATION SET PROTECTION MODE MaxAvailability;
enable fast_start failover;

出来个小提示:Zero Data Loss Mode … 很装 X 的感 Jo.

StaticConnectIdentifier

有个 StaticConnectIdentifier 参数,默认是这样的:

这个参数有问题,执行角色互换时换到一半就中止报错,需要改一下。

edit database 'DB1' set property StaticConnectIdentifier='DB1';

edit database 'DB2' set property StaticConnectIdentifier='DB2';

参数值要跟 tnsnames 文件里的连接名要匹配。

-- 查看
show configuration; 

observer 进程没开启。 开启之前先看看能不能手动切换:

手动切换角色

switchover to 'DB2';

我在这里是连接到主库执行的切换,如果是在12c数据库上的话会报一个错误,会提示让你连接到备库再执行切换。

而到19c版本,即使连接的是主库,它会自动连接到备库再执行切换(黄框)。

sqlplus查看:

select name,db_unique_name,database_role,open_mode from v$database;

之前的备库(DB2),变成主库了,并且已经处于读写状态了:

再看看之前的主库(DB1),变成备库了,并且处于read only with apply,

也就是说已经开始应用日志了,自动的。

主库:糟了,我成替身了!

手动切换成功了那么自动切换也就没什么大问题了。

自动切换

开启observer

observer “观察”到主库异常时(比如断电)会执行故障转移。

dgmgrl -silent sys/0@DB1 'start observer' &

模拟灾难

shutdown abort 命令也会使 observer 做出反应。

不要随便shutdown abort,这条命令相当于把服务器电源给踹了。

观察

这个是 DB1 实例所在主机(h1):

这个是 DB2 实例所在主机(h2):

当敲完 shutdown abort 后就立马开始警告了。

30 秒(FastStartFailoverThreshold)后就开始故障转移了,且成功了(红框)。

下面的几行警告是因为之前的主库变备库,但是已经被 shutdown了,提示连不到备库。

手动开启备库

startup

注意:这里我只敲了“startup”,其它啥都没干。

只是查看了几下开启状态,刚开始是 mount,然后是 read only,最后是 read only with apply 了。

已经开始应用了,自动地。

看看 h1 主机:

看看h2主机:

打码部分是命令敲错了。

完事了!↓↓↓

一切正常,仿佛什么都没发生过一样。

嗯~ 赛高尼 high 铁鸭子哒~

看看日志

当 shutdown abort 时,DB1(现在的主库)日志:

而DB2(当时的主库)的日志没动静了。(毕竟电源被踹了)

开启备库(DB2)后,DB1 日志:

报错没了。

DB2(之前的主库,现在的备库)日志里看到了这样的信息:

整个过程我只做了:

shutdown abort 和手动启动备库。

而且 shutdown abort 是模拟了一个小灾难,不能算是我的操作。

故障转移都是由 oracle 自动完成的。

包括手动启动备库之后的应用日志,也是自动给我做好了。

也就是说,主库挂了变备库了,你唯一要做的就是 startup 它,其它的事情 oracle 自动给你做好了。

当然,在业务环境当中发生这样的事故,情况要复杂的多得多。

我这只是简单的学习环境,可以说是"理想环境"。

其它

执行 alter system set dg_broker_start=true; 后,

OS 里可以查到一个进程叫 dmon.

执行 dgmgrl -silent sys/0@DB1 'start observer;' & 后,可以这样查看:

observer的关闭:

dgmgrl 的帮助非常友好:直接复制粘贴就好了,Oracle一贯的风格。


http://chatgpt.dhexx.cn/article/dbqr0Ekb.shtml

相关文章

oracle dataguard延迟,dataguard延迟日志应用的问题

本帖最后由 lfree 于 2012-12-11 12:07 编辑 我管的dataguard使用recover managed standby database disconnect from session delay 720。 我发现一个问题,如果使用asm作为存储,会出现"大量“读取操作。 snap.jpg (10 KB, 下载次数: 43) 2012-12-1…

Oracle Dataguard(主库为 Oracle rac 集群)配置教程(01)—— dataguard 服务器安装 Oracle 软件

Oracle Dataguard(主库为 Oracle rac 集群)配置教程(01)—— dataguard 服务器安装 Oracle 软件 / 本专栏详细讲解 Oracle Dataguard(Oracle 版本为11g,主库为双节点 Oracle rac 集群)的配置过程…

Oracle DataGuard

一、DataGuard介绍 DataGuard是Oracle的一种高可用性数据库方案,主要用于数据容灾和读写分离。 数据库角色 Primary:主库 Standby:备库 Standby类型 物理standby:redolog以介质恢复的方式实现同步。用于数据备份(11G也可以读写分离)。 逻辑…

Data Guard原理

文章来源于网络整理 DG通过提供冗余数据来提供数据保护 1.常用于异地容灾和小企业的高可用解决方案 2.虽然可以在Standby机器上执行只读查询,从而分散Primary数据库的性能压力,但是绝不是性能解决方案 DataGuard介绍 在DG环境中,至少会有两…

基于Java的员工工资管理系统

​ 源码编号:F-A15 项目类型:Java SE项目(awtswing) 项目名称:基于Java的员工工资管理系统(EmployeeSalary) 用户类型:双角色(员工、管理员) 主要技术:ja…

Java工程师工资水平出炉!真厉害了

Java因为其十分适用于企业级开发的特点,所以一直是国内大厂最主要使用的语言之一,也是应用最广泛的编程语言。 也由于Java主要用于开发企业级应用,市场需求同比其他语言来说会更大一些,自然它的起薪也相对较高,因而很多…

Java培训出来后一般多少工资

学完Java培训出来后一般多少工资呢?这是很多人都比较关心的一个问题,小编在这里告诉大家,java技术这个岗位分为初级、中级和高级,每个等级的工资情况也是不一样,来看看下面的详细介绍。 Java培训出来后一般多少工资?Java程序员薪…

2022上海Java工资收入概览

微信公众号,关注:georgezheng 越来越多的人选择从事IT,接触计算机互联网,除了学习复杂庞大的知识体系,也比较关注各地区Java工资收入,我收集了上海的信息做一次整理,数据来源职友集和平…

Java基础(员工工资管理系统)

项目介绍: 某公司的雇员分为以下若⼲类: SalariedEmployee:拿固定⼯资的员⼯。 HourlyEmployee:按⼩时拿⼯资的员⼯,每⽉⼯作超出160⼩时的部分按照1.5倍⼯资发放 SalesEmployee:销售⼈员,⼯资由⽉销售额和…

2020年5大一线城市Java薪资水平汇总,你还差多少呢?

程序员作为薪资最高的行业之一,一直是很多人转行的热门首选行业。Java程序员又在所有程序员中占比最大, 因此,Java程序员的薪资就能够很好的代表行业的薪资水准。 今天就为大家整理5大热门城市的Java薪资情况,看看你还差多少,你又想拿多少?或者你希望去哪个城市发展呢?…

Redis LRU

一:Redis内存驱逐的几种策略 检测易失数据(可能会过期的数据集server.db[i].expires ) ① volatile-lru:挑选最近最少使用的数据淘汰 ② volatile-lfu:挑选最近使用次数最少的数据淘汰 ③ volatile-ttl&#xff1a…

LRU链表及LRU缓存

注:本文分析基于linux-4.18.0-193.14.2.el8_2内核版本,即CentOS 8.2 1、 关于LRU LRU即Least recently used,也就是最近最少使用,一般用作缓存淘汰上,它的核心思想是——如果一个数据在最近一段时间没有被访问到&…

14.1 LRU链表

在最近几十年操作系统的发展过程中,有很多页面交换算法,其中每个算法都有各自的优点和缺点。linux内核中采用的页面交换算法主要是LRU算法和第二次机会法(second chance)。 LRU链表 LRU是least recently used(最近最少使用)的缩写…

mysql lru_MySQL · 源码分析 · InnoDB LRU List刷脏改进之路

之前的一篇内核月报MySQL 引擎特性 InnoDB Buffer Pool 中对InnoDB Buffer pool的整体进行了详细的介绍。文章已经提到了LRU List以及刷脏的工作原理。本篇文章着重从MySQL 5.7源码层面对LRU List刷脏的工作原理,以及Percona针对MySQL LRU Flush的一些性能问题所做…

图解LRU算法

目录 一、什么是LRU算法? 二、基于双向链表Map实现LRU算法 1. 用双向链表看成cache缓存, 数据存放在链表上的每个节点上。 2. 用Map记录访问cache的历史, 只要访问了 cache就将节点放置Map里。 3. 图解移动节点和淘汰策略过程 三、完整代码 四、借助LinkedHashMap实现 一…

mysql lru_浅析MySQL的lru链表

一、简述传统的LRU链表 LRU:Least Recently Used 相信大家对LRU链表是不陌生的,它算是一种基础的数据结构吧,而且想必面试时也被问到过什么是LRU链表,甚至是让你手写一个LRU链表。 想必你已经知道了MySQL的Buffer Pool机制以及MyS…

LRU实现算法

转载自:https://www.cnblogs.com/Dhouse/p/8615481.html 四种实现方式 LRU 1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过&#x…

Redis LRU算法

一、配置Redis内存淘汰策略 maxmemory 100mbmaxmemory-policy allkeys-lrumaxmemory-samples 5注意:Redis的LRU算法并非完整的实现,而是近似LRU的算法,详细介绍点击这里 二、LRU实现原理 1、双向链表 哈希表 1、哈希表:查找快&…

LRU链表介绍

文章目录 1. 简介2. LRU 组织 2.1 LRU 链表2.2 LRU Cache2.3 LRU 移动操作 2.3.1 page 加入 LRU2.3.2 其他 LRU 移动操作3. LRU 回收 3.1 LRU 更新3.2 Swappiness3.3 反向映射3.4 代码实现 3.4.1 struct scan_control3.4.2 shrink_node()3.4.3 shrink_list()3.4.4 shrink_acti…

LRU页面回收

内存回收算法总是会在一定的时间将一些内存回收, 内存回收算法是通过LRU链表对page页面进行管理的,对于那些新的页面会将其插入到LRU链表头,回收时将返回LRU链表末尾的元素,代表老化程度最高的页面 基本数据结构 typedef struct…