为记录的更详细点,文章经过二次编辑,有几张图的时间对不上,不过不影响查阅。
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;
![](https://img-blog.csdnimg.cn/img_convert/9146f84b52b864560645aeefda2928f5.png)
如果没有启用归档模式,数据库要 mount 状态执行:
alter database archivelog;
standby log
查看redo概况:
select bytes/1024/1024 from v$log
where group# in (select group# from v$logfile);
![](https://img-blog.csdnimg.cn/img_convert/b5d84b6293a3f8c2b9547d25335d28c2.png)
创建(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;
![](https://img-blog.csdnimg.cn/img_convert/1d324d329d9c452c98ab719002e863aa.png)
查看:
可以看到 BD_UNIQUE_NAME 变成 DB1 了,之前是 DB0.
![](https://img-blog.csdnimg.cn/img_convert/dfc1b88c2ae5bdfa004561645ba2a414.png)
准备配置备库
#未能正常启动就回去看看哪里疏漏了什么细节。
#如果可以正常开启数据库就把 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
执行上面三条替换命令,DB1 和 DB2 就互换过来了:
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复制
![]() 不出意外的话,能看到这么一行: ![]() 如有报错,看看报错信息,回去看看哪里搞错了,删除生成的"问题文件",再尝试能否成功。 |
到sqlplus查看:
![]() database_role 为 PHYSICAL STANDBY,duplicate 操作完成后就会启动到 mount 状态。 |
开始同步(应用日志)
备库进sqlplus,应用日志
![]() 可以看到,open_mode 为 read only with apply. |
取消应用:
![]() 取消应用日志后,就变成 read only 了。 |
完成基本搭建了
基本管理
temp_undo
最好开启 temp_undo:
alter system set temp_undo_enabled=true;
![](https://img-blog.csdnimg.cn/img_convert/f6305d5c275d2bc494eab1ab1845fcb4.png)
![](https://img-blog.csdnimg.cn/img_convert/62878a98c46009e98714b94c1a96d851.png)
dg_broker
alter system set dg_broker_start=true;
![](https://img-blog.csdnimg.cn/img_convert/6ad2ea7f07edebc7864535d7b0b63e27.png)
![](https://img-blog.csdnimg.cn/img_convert/270daf30531c2830ed728b272488f5a7.png)
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 状态。
![](https://img-blog.csdnimg.cn/img_convert/2768c2d3388f54de93628548b5b0be0d.png)
![](https://img-blog.csdnimg.cn/img_convert/91128269da746831095186364a6a0ed9.png)
开启闪回
alter database flashback on;
![](https://img-blog.csdnimg.cn/img_convert/d611d0c78f45a7faa98ea8665c016403.png)
dgmgrl
到 dgmgrl 里做一些骚操作吧!
dgmgrl sys/0@DB1
![](https://img-blog.csdnimg.cn/img_convert/0c5574a3762625053f60fd333cea90c0.png)
注:这里先连到主库。
新建一个配置
新建一个配置,就叫 dgtest 吧。
create configuration dgtest as primary database is 'DB1' connect identifier is 'DB1';
add database 'DB2' as connect identifier is 'DB2';
![](https://img-blog.csdnimg.cn/img_convert/3681c001d46694eb8bac90b6bb835cea.png)
查看
show configuration;
![](https://img-blog.csdnimg.cn/img_convert/6c075aeb0bf780e6ccc1e5f9b65290aa.png)
还未开启。
show database verbose 'DB1';
show database verbose 'DB2';
![](https://img-blog.csdnimg.cn/img_convert/68fd163c8c8e7531ec03724d78f33c74.png)
两个都是 disable 状态。
启用
enable configuration;
enable database 'DB1';
enable database 'DB2';
![](https://img-blog.csdnimg.cn/img_convert/ed388c31673a501d6980b9badf2b66ae.png)
查看
show database verbose 'DB1';
![](https://img-blog.csdnimg.cn/img_convert/91b0f22fea334b980ab7083f1c7b562b.png)
show database verbose 'DB2';
![](https://img-blog.csdnimg.cn/img_convert/a5425b4ece6ef954b4bba988226cc41b.png)
show configuration;
![](https://img-blog.csdnimg.cn/img_convert/a69fed21e281646a7ceb11b28df4e579.png)
没有报错,也没有警告。 就很舒服。
#注:有些状态内容是一分钟刷新一次的,所以做完更改可能要稍微等一会才能看到变化。
做一些改动
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'; |
![](https://img-blog.csdnimg.cn/img_convert/1aa7ec0b290924627094f8d80e609def.png)
EDIT CONFIGURATION SET PROTECTION MODE MaxAvailability;
enable fast_start failover;
![](https://img-blog.csdnimg.cn/img_convert/53902cb8189fc2162d6dfbdee5c6438c.png)
出来个小提示:Zero Data Loss Mode … 很装 X 的感 Jo.
StaticConnectIdentifier
有个 StaticConnectIdentifier 参数,默认是这样的:
![](https://img-blog.csdnimg.cn/img_convert/d685bc9119e5f241ecd4c0d5f9910f95.png)
这个参数有问题,执行角色互换时换到一半就中止报错,需要改一下。
edit database 'DB1' set property StaticConnectIdentifier='DB1'; edit database 'DB2' set property StaticConnectIdentifier='DB2'; |
参数值要跟 tnsnames 文件里的连接名要匹配。
-- 查看
show configuration;
![](https://img-blog.csdnimg.cn/img_convert/f3f75dde3e12575e8aa1384e064f57ff.png)
observer 进程没开启。 开启之前先看看能不能手动切换:
手动切换角色
switchover to 'DB2';
![](https://img-blog.csdnimg.cn/img_convert/db9bac31d5b2ba6acabb34fb0939e6b4.png)
我在这里是连接到主库执行的切换,如果是在12c数据库上的话会报一个错误,会提示让你连接到备库再执行切换。
而到19c版本,即使连接的是主库,它会自动连接到备库再执行切换(黄框)。
sqlplus查看:
select name,db_unique_name,database_role,open_mode from v$database;
之前的备库(DB2),变成主库了,并且已经处于读写状态了:
![](https://img-blog.csdnimg.cn/img_convert/2ead0bbe516a993352eb80e2911406f9.png)
再看看之前的主库(DB1),变成备库了,并且处于read only with apply,
也就是说已经开始应用日志了,自动的。
![](https://img-blog.csdnimg.cn/img_convert/21880361bf62fff79ad0bb40980fea9b.png)
主库:糟了,我成替身了!
手动切换成功了那么自动切换也就没什么大问题了。
自动切换
开启observer
observer “观察”到主库异常时(比如断电)会执行故障转移。
dgmgrl -silent sys/0@DB1 'start observer' &
模拟灾难
shutdown abort 命令也会使 observer 做出反应。
不要随便shutdown abort,这条命令相当于把服务器电源给踹了。
![](https://img-blog.csdnimg.cn/img_convert/49ef7f475d0acc73edc8d63970d46dc1.png)
观察
这个是 DB1 实例所在主机(h1):
![](https://img-blog.csdnimg.cn/img_convert/71d7b9b5ebb00954fb61347738c3b3f6.png)
这个是 DB2 实例所在主机(h2):
![](https://img-blog.csdnimg.cn/img_convert/24427d7d3b4c6a29382b3bc5e9f92896.png)
当敲完 shutdown abort 后就立马开始警告了。
30 秒(FastStartFailoverThreshold)后就开始故障转移了,且成功了(红框)。
下面的几行警告是因为之前的主库变备库,但是已经被 shutdown了,提示连不到备库。
手动开启备库
startup
![](https://img-blog.csdnimg.cn/img_convert/fdc2be8bbc48c7e361645589bc75dccc.png)
注意:这里我只敲了“startup”,其它啥都没干。
只是查看了几下开启状态,刚开始是 mount,然后是 read only,最后是 read only with apply 了。
已经开始应用了,自动地。
看看 h1 主机:
![](https://img-blog.csdnimg.cn/img_convert/01964bfd470ec4d28e85bb33ffb6b7c0.png)
看看h2主机:
![](https://img-blog.csdnimg.cn/img_convert/27f2b497695d65f17608e65a3be4651a.png)
打码部分是命令敲错了。
完事了!↓↓↓
![](https://img-blog.csdnimg.cn/img_convert/0767f2fefda9ba3677d57a2f7199ea79.png)
一切正常,仿佛什么都没发生过一样。
嗯↗嗯~ 赛高尼 high 铁鸭子哒~
![](https://img-blog.csdnimg.cn/img_convert/4a7727ca09c89e4733049203fc91cb78.jpeg)
看看日志
当 shutdown abort 时,DB1(现在的主库)日志:
![](https://img-blog.csdnimg.cn/img_convert/cb2554afe734b6399a73e1083bae7508.png)
而DB2(当时的主库)的日志没动静了。(毕竟电源被踹了)
开启备库(DB2)后,DB1 日志:
![](https://img-blog.csdnimg.cn/img_convert/5c09368813c68b45b581ef3f075492f5.png)
报错没了。
DB2(之前的主库,现在的备库)日志里看到了这样的信息:
![](https://img-blog.csdnimg.cn/img_convert/50b9a97ba8166629450e0cf501596921.png)
整个过程我只做了:
shutdown abort 和手动启动备库。
而且 shutdown abort 是模拟了一个小灾难,不能算是我的操作。
故障转移都是由 oracle 自动完成的。
包括手动启动备库之后的应用日志,也是自动给我做好了。
也就是说,主库挂了变备库了,你唯一要做的就是 startup 它,其它的事情 oracle 自动给你做好了。
当然,在业务环境当中发生这样的事故,情况要复杂的多得多。
我这只是简单的学习环境,可以说是"理想环境"。
其它
执行 alter system set dg_broker_start=true; 后,
OS 里可以查到一个进程叫 dmon.
![](https://img-blog.csdnimg.cn/img_convert/c6ef2b879e8bf112b2825eec15ead280.png)
执行 dgmgrl -silent sys/0@DB1 'start observer;' & 后,可以这样查看:
![](https://img-blog.csdnimg.cn/img_convert/49e800d77ff8e4f593bb63a07ea0091e.png)
observer的关闭:
![](https://img-blog.csdnimg.cn/img_convert/a99e9f486063d3f0bf62701f7cea7587.png)
dgmgrl 的帮助非常友好:直接复制粘贴就好了,Oracle一贯的风格。
![](https://img-blog.csdnimg.cn/img_convert/b4e23a0007f2efb1a2e99e7d86835134.png)