1. 什么是读写分离?
2. 为什么要做读写分离?
3. ORACLE读写分离的方式,各有优缺点?
4. 详解其中一种ORACLE读写分离方式。
如图:
为了确保数据库产品的稳定性,很多数据库拥有双机热备功能。也就是,第一台 数据库服务器,是对外提供增删改业务的生产服务器;第二台数据库服务器,主要进 行读的操作。
2台数据库服务器,其中一台数据库服务器进行数据写入操作,另一台数据库服 务器进行数据的读取。2台数据库之间数据要进去快速的数据同步。
因为数据库的“写”(写10000条数据到oracle可能要3分钟)操作是比较耗时的。
但是数据库的“读”(从oracle读10000条数据可能只要5秒钟)。
所以读写分离,解决的是,数据库的写入,影响了查询的效率。
1) 增加冗余
2) 增加了机器的处理能力
3) 对于读操作为主的应用,使用读写分离是最好的场景,因为可以确保写的服务器压力更小,而读又可以接受点时间上的延迟。
1) 物理服务器增加,负荷增加
2) 主从只负责各自的写和读,极大程度的缓解X锁和S锁争用①
3) 从库同步主库的数据和主库直接写还是有区别的,通过主库发送来的binlog恢复数据,但是,最重要区别在于主库向从库发送binlog是异步的,从库恢复数据也是异步的
4) 读写分离适用与读远大于写的场景,如果只有一台服务器,当select很多时,update和delete会被这些select访问中的数据堵塞,等待select结束,并发性能不高。 对于写和读比例相近的应用,应该部署双主相互复制
5) 可以在从库启动是增加一些参数来提高其读的性能,当然这些设置也是需要根据具体业务需求来定得,不一定能用上
6) 分摊读取。假如我们有1主3从,不考虑上述1中提到的从库单方面设置,假设现在1 分钟内有10条写入,150条读取。那么,1主3从相当于共计40条写入,而读取总数没变,因此平均下来每台服务器承担了10条写入和50条读取(主库不 承担读取操作)。因此,虽然写入没变,但是读取大大分摊了,提高了系统性能。另外,当读取被分摊后,又间接提高了写入的性能。所以,总体性能提高了,说白了就是拿机器和带宽换性能。
7) 复制另外一大功能是增加冗余,提高可用性,当一台数据库服务器宕机后能通过调整另外一台从库来以最快的速度恢复服务,因此不能光看性能,也就是说1主1从也是可以的。
读写分离的重点其实就是数据同步,能实现数据实时同步的技术很多,基于OS层(例如VERITAS VVR),基于存储复制(中高端存储大多都支持),基于应用分发或者基于数据库层的技术。因为数据同步可能并不是单一的DB整库同步,会涉及到业务数据选择以及多源整合等问题,因此OS复制和存储复制多数情况并不适合做读写分离的技术首选。
基于日志的Oracle复制技术,Oracle自身组件可以实现,同时也有成熟的商业软件。选商业的独立产品还是Oracle自身的组件功能,这取决于多方面的因素。比如团队的相应技术运维能力、项目投入成本、业务系统的负载程度等。
无外乎Logical Standby、Stream以及11g的Physical Standby(Active Data Guard),对比来说,Stream最灵活,但最不稳定,11g Physical Standby支持恢复与只读并行,但由于并不是日志的逻辑应用机制,在读写分离的场景中最为局限。如果技术团队对相关技术掌握足够充分,而选型方案的处理能力又能支撑数据同步的要求,采用Oracle自身的组件完全可行。
DG方案也叫ADG方案,英语全称Physical Standby(Active DataGuard)。支持恢复与只读并行,但由于并不是日志的逻辑应用机制,在读写分离的场景中最为局限 ,将生产机的logfiles传递给容灾机,通过Redo Apply技术来保障数据镜像能力,物理上提供了与生产数据库在数据块级的一致性镜像,也叫physical方式。Physical方式支持异步传输方式,但容灾机处在恢复状态,不可用;
通过SQL Apply(即Log Miner)技术,将接收到的日志文件还原成SQL语句,并在逻辑备份数据库上执行,从而达到数据一致性的目的,也叫logical 方式。logical方式只支持同步传输方式,但容灾机可以处在read-only状态
最灵活,但最不稳定
更多出于稳定性、处理能力等考虑。市面上成熟的Oracle复制软件也无外乎几种,无论是老牌的Shareplex,还是本土DSG公司的RealSync和九桥公司的DDS,或是Oracle新贵GoldenGate,都是可供选择的目标。随着GoldenGate被Oracle收购和推广,个人认为GoldenGate在容灾、数据分发和同步方面将大行其道。
wget https://github.com/MyCATApache/Mycat-download/blob/master/1.4-RELEASE/Mycat-server-1.4-release-20151019230038-linux.tar.gz |
tar -zxvf Mycat-server-1.4-release-20151019230038-linux.tar.gz |
vi /etc/profile 末尾加上 MYCAT_HOME=/MyCat/mycat //mycat安装路径 PATH=$PATH:$MYCAT_HOME/bin export MYCAT_HOME PATH |
/MyCat/mycat/conf/wrapper.conf 修改 wrapper.java.command= /usr/java/jdk1.7.0_80/bin/java //修改wrapper.java.command 为jdk的bin目录下的java |
修改配置文件/MyCat/mycat/conf/server.xml
|
<dataNode name="dn1" dataHost="localhost1" database="db1" /> database表空间名称 --> <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="oracle" dbDriver="jdbc"②>
|
配置结束
mycat start |
可以查看日志文件看是否报错/MyCat/mycat/logs/mycat.log
启动报错,导入ojdbc7到mycat的lib目录下
用navicat客户端连接mycat (ip为mycat所在的服务器ip,用户名和密码是在server.xml中配置的user)
navcat for mysql客户端 可能会连接不上报2003-can't connect to mysql server on 10038
需要配置防火墙开启8066端口
vi /etc/sysconfig/iptables #编辑防火墙配置文件,添加以下内容 -A INPUT -m state --state NEW -m tcp -p tcp --dport 8066 -j ACCEPT /etc/init.d/iptables restart #重启防火墙使配置生效 |
|
关闭mycat mycat stop 查看mycat状态 mycat status
|
2个oracle数据库服务器,做单例数据库的读写分离。安装配置略
2个rac数据库服务器。做集群环境的读写分离。安装配置略
单例数据库的读写分离,检测2个oracle服务器宿主机是否安装oracle数据库,是否配置和版本等等一致。安装配置略
Rac集群数据库的读写分离,分别检测2个rac集群数据库是环境配置、oracle版本等一致。安装配置略
相关信息
|
IP地址规划: |
SID: |
db_name: |
db_unique_name |
主数据库 |
192.168.11.120 |
pri |
pri |
pri |
备份数据库 |
192.168.11.121 |
std |
pri |
std |
注意:dbname要配置成一样的,并且关闭防火墙。
环境变量:指向oracle安装的目录
export ORACLE_BASE=/u01/app/oracle export ORACLE_HOME=$ORACLE_BASE/product/11.2.0/db_1 export ORACLE_SID=pri (备库端设置为std) export LD_LIBRARY_PATH=$ORACLE_HOME/bin:/bin:/usr/bin:/usr/local/bin: export CLASSPATH=$ORACLE_HOME/JRE:$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib export PATH=$ORACLE_HOME/bin:$PATH
|
注意:主库需要建好库(执行dbca),备库不需要。
[oracle@pri ~]$sqlplus / as sysdba
查看当前是否强制日志模式:
SYS@pri>select name,log_mode,force_logging from v$database;
NAME LOG_MODE FOR --------- ------------ --- PRI NOARCHIVELOG NO |
SYS@pri>alter database force logging;
成功后再次查看
SYS@pri> select name,log_mode,force_logging fromv$database;
NAME LOG_MODE FOR --------- ------------ --- PRI NOARCHIVELOG YES
|
注意:两端分别创建自己的密码文件好像有问题,备库的密码文件需要跟主库一致,否则导致日志传输不到备库,有待验证。我最后是将主库的密码文件直接copy到备库,重命名后使用。
[oracle@pri~]$ cd $ORACLE_HOME/dbs
[oracle@pridbs]$ ls
hc_pri.dat init.ora initpri.ora lkPRI orapwpri snapcf_pri.f spfilepri.ora |
已经有一个密码文件了
[oracle@pridbs]$ orapwd file=orapwpri password=oracle force=y
这条命令可以手动生成密码文件,force=y的意思是强制覆盖当前已有的密码文件(如果有可以不建立) file= :文件名 password=:数据库超级管理员即sys用户的密码
将主库的密码文件copy给备库,并重命名
[oracle@pri dbs]$ scp orapwpri192.168.11.121:$ORACLE_HOME/dbs/orapwstd
注意:standby redo log的文件大小与primary 数据库online redo log 文件大小相同。standby redo log日志文件组的个数依照下面的原则进行计算:Standby redo log组数公式>=(每个instance日志组个数+1)*instance个数,假如只有一个节点,这个节点有三组redolog,所以Standby redo log组数>=(3+1)*1 == 4,所以至少需要创建4组Standby redo log
查看当前线程与日志组的对应关系及日志组的大小:
SYS@pri>select thread#,group#,bytes/1024/1024 from v$log;
THREAD# GROUP# BYTES/1024/1024 --------------- ------------- ------------------------ 1 1 50 1 2 50 1 3 50 |
如上,我现在的环境有三组redolog,每个日志组的大小都是50M,所以Standby redo log组 数>=(3+1)*1== 4所以至少需要创建4组Standby redo log,大小 均为50M (thread:线 程,只有在多实例数据库才有用的参数,例如RAC环境,单 实例不考虑)
查看当前有哪些日志组及其成员:
SYS@pri>col member for a50
SYS@pri>select group#,member from v$logfile;
GROUP# MEMBER ---------- -------------------------------------------------- 3 /u01/app/oracle/oradata/pri/redo03.log 2 /u01/app/oracle/oradata/pri/redo02.log 1 /u01/app/oracle/oradata/pri/redo01.log |
先手动创建standby log日志组所需的目录:创建新目录只是为了便于区分,并非必须
[oracle@prioradata]$ cd /u01/app/oracle/oradata/
[oracle@prioradata]$ ls
standbylog pri |
新建4个日志组作为standby redolog日志组,大小与原来的日志组一致:由于已经存在 group1-3,,所以group号只能从4开始
SYS@pri>alter database add standby logfile group 4'/u01/app/oracle/oradata/standbylog/std_redo04.log' size 50m;
SYS@pri>alter database add standby logfile group 5 '/u01/app/oracle/oradata/standbylog/std_redo05.log'size 50m;
SYS@pri>alter database add standby logfile group 6'/u01/app/oracle/oradata/standbylog/std_redo06.log' size 50m;
SYS@pri>alter database add standby logfile group 7'/u01/app/oracle/oradata/standbylog/std_redo07.log' size 50m;
查看standby 日志组的信息:
SYS@pri>select group#,sequence#,status, bytes/1024/1024 from v$standby_log;
GROUP# SEQUENCE# STATUS BYTES/1024/1024 ---------- ------------------ ------------------- ------------------------ 4 0 UNASSIGNED 50 5 0 UNASSIGNED 50 6 0 UNASSIGNED 50 7 0 UNASSIGNED 50 |
查看当前有哪些日志组及其成员:
SYS@pri>set pagesize 100
SYS@pri>col member for a60
SYS@pri>select group#,member from v$logfile order by group#;
GROUP# MEMBER ------------ ------------------------------------------------------------ 1 /u01/app/oracle/oradata/pri/redo01.log 2 /u01/app/oracle/oradata/pri/redo02.log 3 /u01/app/oracle/oradata/pri/redo03.log 4 /u01/app/oracle/oradata/standbylog/std_redo04.log 5 /u01/app/oracle/oradata/standbylog/std_redo05.log 6 /u01/app/oracle/oradata/standbylog/std_redo06.log c /u01/app/oracle/oradata/standbylog/std_redo07.log |
查看spfile的路径:
SYS@pri>show parameter spfile;
NAME TYPE VALUE ----------- ----------- ----------------------------------------------------------------- spfile string /u01/app/oracle/product/11.2.0/db_1/dbs/spfilepri.ora |
用spfile创建一个pfile,用于修改:
SYS@pri>create pfile from spfile;
修改主库的pfile:/u01/app/oracle/product/11.2.0/db_1/dbs/ initpri.ora
[oracle@pri~]$ cd $ORACLE_HOME/dbs
[oracle@pri~]$ vim initpri.ora
pri.__db_cache_size=318767104 pri.__java_pool_size=4194304 pri.__large_pool_size=4194304 pri.__oracle_base='/u01/app/oracle'#ORACLE_BASE set from environment pri.__pga_aggregate_target=335544320 pri.__sga_target=503316480 pri.__shared_io_pool_size=0 pri.__shared_pool_size=163577856 pri.__streams_pool_size=0 *.audit_file_dest='/u01/app/oracle/admin/pri/adump' *.audit_trail='db' *.compatible=' 11.2.0.4.0 ' *.control_files='/u01/app/oracle/oradata/pri/control01.ctl','/u01/app/oracle/flash_recovery_area/pri/control02.ctl' *.db_block_size=8192 *.db_domain='' *.db_name='pri' *.db_recovery_file_dest='/u01/app/oracle/flash_recovery_area' *.db_recovery_file_dest_size=4070572032 *.diagnostic_dest='/u01/app/oracle' *.dispatchers='(PROTOCOL=TCP) (SERVICE=priXDB)' *.log_archive_format='%t_%s_%r.dbf' *.memory_target=836763648 *.open_cursors=300 *.processes=150 *.remote_login_passwordfile='EXCLUSIVE' *.undo_tablespace='UNDOTBS1' |
以下内容是需要新增加的:
*.db_unique_name='pri' DG主库和备库的db_name必须一致,db_unique_name不一致 *.log_archive_config='dg_config=(pri,std)' pri主数据库SID,std备份数据库SID *.log_archive_dest_1='location=/u01/app/oracle/arch valid_for=(all_logfiles,all_roles) db_unique_name=pri' 主数据库的归档日志路径和SID *.log_archive_dest_2='service=std valid_for=(online_logfiles,primary_role) db_unique_name=std' 备份数据库的SID *.log_archive_dest_state_1=enable *.log_archive_dest_state_2=enable *.log_archive_max_processes=4 *.fal_server='std' 备份数据库的SID *.fal_client='pri' 主数据库的SID *.db_file_name_convert='/u01/app/oracle/oradata/std','/u01/app/oracle/oradata/pri' 第一个目录是备份数据库数据文件路径(备份服务器上有此目录),第二个是主数据库数据文件路径 *.log_file_name_convert='/u01/app/oracle/oradata/std','/u01/app/oracle/oradata/pri' 第一个目录是备份数据库数据文件路径(备份服务器上有此目录),第二个是主数据库数据文件路径 *.standby_file_management='auto' |
修改完毕,保存退出
手工创建/u01/app/oracle/arch:
[oracle@pridbs]$ mkdir –p /u01/app/oracle/arch
关闭数据库:
SYS@pri>shutdown immediate;
Database closed. Database dismounted. ORACLE instance shut down. |
用修改过的pfile重新创建一个spfile:
SYS@pri>create spfile from pfile;
此时把数据库改为归档模式:如果当初建库时选择了启用归档,则此步骤忽略
由于当前数据库已关闭,首先需要把数据库启动到mount状态
SYS@pri> startup mount;
ORACLE instance started. Database mounted. |
SYS@pri> alter database archivelog; 启用归档模式
Database altered. |
SYS@pri>alter database open; OPEN数据库
Database altered. |
SYS@pri>archive loglist; 查看是否启用归档模式
SQL>archive log list;
Database log mode Archive Mode Automatic archival Enabled Archive destination /u01/app/oracle/arch Oldest online log sequence 22 Next log sequence to archive 24 Current log sequence 24 |
如上,归档路径已经改为/u01/app/oracle/arch,证明对pfile的修改已生效
查看当前数据库是否使用spfile启动:
SYS@pri>show parameter spfile;
NAME TYPE VALUE ----------- ----------- ----------------------------------------------------------------- spfile string /u01/app/oracle/product/11.2.0/db_1/dbs/spfilepri.ora
|
如上,若能看到spfile的路径,则证明数据库是使用spfile启动的,若没有值,则说明是用 pfile启动的。
确认数据库已经启用归档模式和强制日志模式:
SYS@pri>select name,log_mode,force_logging from v$database;
NAME LOG_MODE FOR --------- ------------------- ------- PRI ARCHIVELOG YES |
主库:
[oracle@pri~]$ cd $ORACLE_HOME/network/admin
[oracle@priadmin]$ vim listener.ora
# listener.ora Network Configuration File: /u01/app/oracle/product/11.2.0/db_1/network/admin/listener.ora # Generated by Oracle configuration tools. LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.11.120)(PORT = 1521)) (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521)) ) ) SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = pri) (ORACLE_HOME = /u01/app/oracle/product/11.2.0/db_1) (SID_NAME = pri) ) ) ADR_BASE_LISTENER = /u01/app/oracle |
主库修改后最终效果如下图:
备库:
[oracle@pri~]$ cd $ORACLE_HOME/network/admin
[oracle@priadmin]$ vim listener.ora
# listener.ora Network Configuration File: /u01/app/oracle/product/11.2.0/db_1/network/admin/listener.ora # Generated by Oracle configuration tools. LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.11.121)(PORT = 1521)) (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521)) ) ) SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = std) (ORACLE_HOME = /u01/app/oracle/product/11.2.0/db_1) (SID_NAME = std) ) ) ADR_BASE_LISTENER = /u01/app/oracle |
备库修改后最终效果如下图:
使新增加的监听生效: (主库和备库端都要做)
[oracle@priadmin]$ lsnrctl stop
[oracle@priadmin]$ lsnrctl start
确认新增加的静态监听有效:
主库:
[oracle@pri~]$ lsnrctl status
..........................................(N行省略) Services Summary... Service "pri" has 2 instance(s). Instance "pri", status UNKNOWN, has 1 handler(s) for this service... Instance "pri", status READY, has 1 handler(s) for this service... Service "priXDB" has 1 instance(s). Instance "pri", status READY, has 1 handler(s) for this service... The command completed successfully |
备库:
[oracle@std~]$ lsnrctl status
..........................................(N行省略) Services Summary... Service "std" has 2 instance(s). Instance "std", status UNKNOWN, has 1 handler(s) for this service... The command completed successfully |
如上,静态监听添加成功
[oracle@priadmin]$ cd /u01/app/oracle/product/11.2.0/db_1/network/admin
[oracle@priadmin]$ ls
listener.ora samples tnsnames.ora listener.ora_bak shrept.lst tnsnames.ora_bak |
vimtnsnames.ora
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/11.2.0/db_1/network/admin/tnsnames.ora # Generated by Oracle configuration tools. pri = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.11.120)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = pri) ) ) std = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.11.121)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = std) ) ) |
编辑结果如下图:
保证主库和备库的tnsnames.ora文件中的内容完全相同,可以把修改后的文件直接传给备库。
[oracle@priadmin]$ scp tnsnames.ora 192.168.11.121:$ORACLE_HOME/network/admin
tnsnames.ora 100% 925 0.9KB/s 00:00 |
首先,在主库端把pfile拷贝给备库端的$ORACLE_HOME/dbs目录下,并重命名:
[oracle@std ~]$ cd $ORACLE_HOME/dbs
[oracle@ std dbs]$ ls
hc_std.dat init.ora initstd.ora lkSTD orapwstd spfilestd.ora |
从主库拷贝,主库执行命令
[oracle@pridbs]$ scp initpri.ora 192.168.2.253:$ORACLE_HOME/dbs/initstd.ora
然后在备库端进行修改:
[oracle@std~]$ cd $ORACLE_HOME/dbs
[oracle@stddbs]$ vim initstd.ora
pri.__db_cache_size=318767104 pri.__java_pool_size=4194304 pri.__large_pool_size=4194304 pri.__oracle_base='/u01/app/oracle'#ORACLE_BASE set from environment pri.__pga_aggregate_target=335544320 pri.__sga_target=503316480 pri.__shared_io_pool_size=0 pri.__shared_pool_size=163577856 pri.__streams_pool_size=0 *.audit_file_dest='/u01/app/oracle/admin/std/adump' *.audit_trail='db' *.compatible='11.2.0.0.0' *.control_files='/u01/app/oracle/oradata/std/control01.ctl','/u01/app/oracle/oradata/std/control02.ctl' *.db_block_size=8192 *.db_domain='' *.db_name='pri' DG主库和备库的db_name必须一致,db_unique_name不一致 *.db_recovery_file_dest='/u01/app/oracle/flash_recovery_area' *.db_recovery_file_dest_size=4070572032 *.diagnostic_dest='/u01/app/oracle' *.dispatchers='(PROTOCOL=TCP) (SERVICE=stdXDB)' *.log_archive_format='%t_%s_%r.dbf' *.memory_target=836763648 *.open_cursors=300 *.processes=150 *.remote_login_passwordfile='EXCLUSIVE' *.undo_tablespace='UNDOTBS1' |
以下需要手工添加:
*.db_unique_name='std' *.log_archive_config='dg_config=(pri,std)' *.log_archive_dest_1='location=/u01/app/oracle/arch valid_for=(all_logfiles,all_ roles) db_unique_name=std' *.log_archive_dest_2='service=pri valid_for=(online_logfiles,primary_role) db _unique_name=pri' *.log_archive_dest_state_1=enable *.log_archive_dest_state_2=enable *.log_archive_max_processes=4 *.fal_server='pri' *.fal_client='std' *.db_file_name_convert='/u01/app/oracle/oradata/pri','/u01/app/oracle/oradata /std' *.log_file_name_convert='/u01/app/oracle/oradata/pri','/u01/app/oracle/oradat a/std' *.standby_file_management='auto' |
修改完毕,保存退出
注意:整个搭建过程最需要留意的就是主库和备库的PFILE配置,建议修改完后仔细对照主备库PFILE的区别
mkdir -pv /u01/app/oracle/admin/std/adump
mkdir -pv /u01/app/oracle/diag/rdbms/std/std/trace
mkdir -pv /u01/app/oracle/arch
mkdir -pv /u01/app/oracle/oradata/std
mkdir -pv /u01/app/oracle/oradata/standbylog
mkdir -pv /u01/app/oracle/flash_recovery_area
[oracle@std~]$ sqlplus / as sysdba
SYS@std>create spfile from pfile;
将数据库启动到nomount状态:
SYS@std>startup nomount;
ORACLE instance started. Total System Global Area 839282688 bytes Fixed Size 2233000 bytes Variable Size 482348376 bytes Database Buffers 352321536 bytes Redo Buffers 2379776 bytes |
[oracle@std~]$ rman target sys/oracle@pri auxiliary sys/oracle@std
Recovery Manager: Release 11.2.0.3.0 - Production on Tue Apr 15 16:39:28 2014
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
connected to target database: PRI (DBID=775616459) connected to auxiliary database: PRI (not mounted) |
RMAN>duplicate target database for standby from active database nofilenamecheck;
这条命令可以直接恢复数据文件,standby控制文件,standby日志组,非常霸道
Starting Duplicate Db at 16-MAR-16 using target database control file instead of recovery catalog allocated channel: ORA_AUX_DISK_1 channel ORA_AUX_DISK_1: SID=134 device type=DISK contents of Memory Script: { backup as copy reuse targetfile '/u01/app/oracle/product/11.2.0/db_1/dbs/orapwpri' auxiliary format '/u01/app/oracle/product/11.2.0/db_1/dbs/orapwstd' ; } executing Memory Script Starting backup at 16-MAR-16 allocated channel: ORA_DISK_1 channel ORA_DISK_1: SID=140 device type=DISK Finished backup at 16-MAR-16 contents of Memory Script: { backup as copy current controlfile for standby auxiliary format '/u01/app/oracle/oradata/std/control01.ctl'; } executing Memory Script Starting backup at 16-MAR-16 using channel ORA_DISK_1 channel ORA_DISK_1: starting datafile copy copying standby control file output file name=/u01/app/oracle/product/11.2.0/db_1/dbs/snapcf_pri.f tag=TAG20160316T110737 RECID=2 STAMP=906635257 channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:01 Finished backup at 16-MAR-16 contents of Memory Script: { sql clone 'alter database mount standby database'; } executing Memory Script sql statement: alter database mount standby database contents of Memory Script: { set newname for tempfile 1 to "/u01/app/oracle/oradata/std/temp01.dbf"; switch clone tempfile all; set newname for datafile 1 to "/u01/app/oracle/oradata/std/system01.dbf"; set newname for datafile 2 to "/u01/app/oracle/oradata/std/sysaux01.dbf"; set newname for datafile 3 to "/u01/app/oracle/oradata/std/undotbs01.dbf"; set newname for datafile 4 to "/u01/app/oracle/oradata/std/users01.dbf"; backup as copy reuse datafile 1 auxiliary format "/u01/app/oracle/oradata/std/system01.dbf" datafile 2 auxiliary format "/u01/app/oracle/oradata/std/sysaux01.dbf" datafile 3 auxiliary format "/u01/app/oracle/oradata/std/undotbs01.dbf" datafile 4 auxiliary format "/u01/app/oracle/oradata/std/users01.dbf" ; sql 'alter system archive log current'; } executing Memory Script executing command: SET NEWNAME renamed tempfile 1 to /u01/app/oracle/oradata/std/temp01.dbf in control file executing command: SET NEWNAME executing command: SET NEWNAME executing command: SET NEWNAME executing command: SET NEWNAME Starting backup at 16-MAR-16 using channel ORA_DISK_1 channel ORA_DISK_1: starting datafile copy input datafile file number=00001 name=/u01/app/oracle/oradata/pri/system01.dbf output file name=/u01/app/oracle/oradata/std/system01.dbf tag=TAG20160316T110744 channel ORA_DISK_1: datafile copy complete, elapsed time: 00:01:38 channel ORA_DISK_1: starting datafile copy input datafile file number=00002 name=/u01/app/oracle/oradata/pri/sysaux01.dbf output file name=/u01/app/oracle/oradata/std/sysaux01.dbf tag=TAG20160316T110744 channel ORA_DISK_1: datafile copy complete, elapsed time: 00:01:09 channel ORA_DISK_1: starting datafile copy input datafile file number=00003 name=/u01/app/oracle/oradata/pri/undotbs01.dbf output file name=/u01/app/oracle/oradata/std/undotbs01.dbf tag=TAG20160316T110744 channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:15 channel ORA_DISK_1: starting datafile copy input datafile file number=00004 name=/u01/app/oracle/oradata/pri/users01.dbf output file name=/u01/app/oracle/oradata/std/users01.dbf tag=TAG20160316T110744 channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:01 Finished backup at 16-MAR-16 sql statement: alter system archive log current contents of Memory Script: { switch clone datafile all; } executing Memory Script datafile 1 switched to datafile copy input datafile copy RECID=2 STAMP=906635463 file name=/u01/app/oracle/oradata/std/system01.dbf datafile 2 switched to datafile copy input datafile copy RECID=3 STAMP=906635463 file name=/u01/app/oracle/oradata/std/sysaux01.dbf datafile 3 switched to datafile copy input datafile copy RECID=4 STAMP=906635463 file name=/u01/app/oracle/oradata/std/undotbs01.dbf datafile 4 switched to datafile copy input datafile copy RECID=5 STAMP=906635463 file name=/u01/app/oracle/oradata/std/users01.dbf Finished Duplicate Db at 16-MAR-16 |
恢复数据库结束
登陆并查看数据库当前状态:
[oracle@std ~]$ sqlplus / as sysdba
SYS@std>startup
SYS@std>select status from v$instance;
STATUS ------------ MOUNTED (RMAN恢复完直接就是mount状态) |
SYS@std>alter database recover managed standby database disconnect from session;
Database altered. (停止日志应用的命令是:alter database recover managed standby database cancel;) |
查看日志应用情况:
SYS@std>set pagesize 100
SYS@std>select sequence#,applied from v$archived_log order by 1;
SEQUENCE# APPLIED ---------- --------- 8 YES 9 YES 10 YES |
如上,如果发现有个NO的,也是正常的,说明该日志在主库上还没有归档,可以在主库上运行alter system switch logfile;命令来进行日志切换,再到备库查看日志应用情况
先在主库手动切换一下日志:
SYS@pri> alter system switch logfile;
然后查看主库:
SYS@pri>archive log list;
SQL>archive log list;
Database log mode Archive Mode Automatic archival Enabled Archive destination /u01/app/oracle/arch Oldest online log sequence 22 Next log sequence to archive 24 Current log sequence 24 |
备库:
SQL>archive log list;
Database log mode Archive Mode Automatic archival Enabled Archive destination /u01/app/oracle/arch Oldest online log sequence 22 Next log sequence to archive 0 Current log sequence 24 |
结果完全一致,至此,DataGuard的搭建成功!
SQL> selectprocess,client_process,sequence#,status from v$managed_standby;
PROCESS CLIENT_P SEQUENCE# STATUS --------- -------- ---------- ------------ ARCH ARCH 23 CLOSING ARCH ARCH 0 CONNECTED //归档进程 ARCH ARCH 21 CLOSING ARCH ARCH 0 CONNECTED RFS ARCH 0 IDLE RFS UNKNOWN 0 IDLE RFS LGWR 24 IDLE //归档传输进程 RFS UNKNOWN 0 IDLE MRP0 N/A 24 APPLYING_LOG //日志应用进程 d rows selected. |
SQL> selectdatabase_role,protection_mode,protection_level,open_mode from v$database;
DATABASE_ROLE PROTECTION_MODE PROTECTION_LEVEL OPEN_MODE ---------------- -------------------- -------------------- -------------------- PRIMARY MAXIMUM PERFORMANCE MAXIMUM PERFORMANCE READ WRITE |
#standby 端查看,也是一样的。
SQL> selectdatabase_role,protection_mode,protection_level,open_mode from v$database;
DATABASE_ROLE PROTECTION_MODE PROTECTION_LEVEL OPEN_MODE ---------------- -------------------- -------------------- -------------------- PHYSICAL STANDBY MAXIMUM PERFORMANCE MAXIMUM PERFORMANCE MOUNTED |
查看DG的日志信息
SQL> select *from v$dataguard_status;
SQL>shutdown immediate
ORA-01109: database not open Database dismounted. ORACLE instance shut down. |
SQL>startup
ORACLE instance started. Total System Global Area 1188511744 bytes Fixed Size 1364228 bytes Variable Size 754978556 bytes Database Buffers 419430400 bytes Redo Buffers 12738560 bytes Database mounted. Database opened. |
SQL>select database_role,protection_mode,protection_level,open_mode from v$database;
DATABASE_ROLE PROTECTION_MODE PROTECTION_LEVEL OPEN_MODE ---------------- -------------------- -------------------- -------------------- PHYSICAL STANDBY MAXIMUM PERFORMANCE MAXIMUM PERFORMANCE READ ONLY |
SQL>select process,client_process,sequence#,status from v$managed_standby;
PROCESS CLIENT_P SEQUENCE# STATUS --------- -------- ---------- ------------ ARCH ARCH 0 CONNECTED ARCH ARCH 0 CONNECTED ARCH ARCH 0 CONNECTED ARCH ARCH 26 CLOSING RFS ARCH 0 IDLE RFS UNKNOWN 0 IDLE RFS LGWR 27 IDLE 7 rows selected. |
SQL>recover managed standby database using current logfile disconnect from session;
Media recovery complete. |
SQL>select process,client_process,sequence#,status from v$managed_standby;
PROCESS CLIENT_P SEQUENCE# STATUS --------- -------- ---------- ------------ ARCH ARCH 0 CONNECTED ARCH ARCH 0 CONNECTED ARCH ARCH 0 CONNECTED ARCH ARCH 26 CLOSING RFS ARCH 0 IDLE RFS UNKNOWN 0 IDLE RFS LGWR 27 IDLE MRP0 N/A 27 APPLYING_LOG 8 rows selected. |
SQL>select process,client_process,sequence#,status from v$managed_standby;
PROCESS CLIENT_P SEQUENCE# STATUS --------- -------- ---------- ------------ ARCH ARCH 19 CLOSING ARCH ARCH 20 CLOSING ARCH ARCH 0 CONNECTED ARCH ARCH 21 CLOSING MRP0 N/A 22 WAIT_FOR_LOG RFS ARCH 0 IDLE RFS UNKNOWN 0 IDLE RFS UNKNOWN 0 IDLE RFS LGWR 22 IDLE 9 rows selected. |
② S锁和X锁:基本的封锁类型有两种:排它锁(X锁)和共享锁(S锁)。所谓X锁,是事务T对数据A加上X锁时,只允许事务T读取和修改数据A,...所谓S锁,是事务T对数据A加上S锁时,其他事务只能再对数据A加S锁,而不能加X锁,直到T释放A上的S锁,若事务T对数据对象A加了S锁,则T就可以对A进行读取,但不能进行更新(S锁因此又称为读锁),在T释放A上的S锁以前,其他事务可以再对A加S锁,但不能加X锁,从而可以读取A,但不能更新A。
③ balance="0",不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上。balance="1",全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1 ->S1 , M2->S2,并且 M1 与M2 互为主备),正常情况下, M2,S1,S2 都参与 select 语句的负载均衡。balance="2",所有读操作都随机的在 writeHost、 readhost 上分发。balance="3", 所有读请求随机的分发到wiriterHost 对应的 readhost 执行,writerHost不负担读压力,注意 balance=3 只在 1.4 及其以后版本有, 1.3 没有。writeType="0", 所有写操作发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties .writeType="1",所有写操作都随机的发送到配置的 writeHost。writeType="2",没实现。不写入switchType 属性,主mysql挂了,从mysql是否提升为主,-1 表示不自动切换,1 默认值,自动切换,2 基于MySQL主从同步的状态决定是否切换