ORACLE读写分离(注:根据网上资料搭建完成步奏总结)

研究问题:                                            

1.      什么是读写分离?

2.      为什么要做读写分离?

3.      ORACLE读写分离的方式,各有优缺点?

4.      详解其中一种ORACLE读写分离方式。

一、 什么是读写分离?

如图:

       

Ø  官方定义

                为了确保数据库产品的稳定性,很多数据库拥有双机热备功能。也就是,第一台     数据库服务器,是对外提供增删改业务的生产服务器;第二台数据库服务器,主要进         行读的操作。

Ø  我的理解

                2台数据库服务器,其中一台数据库服务器进行数据写入操作,另一台数据库服      务器进行数据的读取。2台数据库之间数据要进去快速的数据同步。

二、 为什么要做读写分离?

        因为数据库的“写”(写10000条数据到oracle可能要3分钟)操作是比较耗时的。

但是数据库的“读”(从oracle10000条数据可能只要5秒钟)。

所以读写分离,解决的是,数据库的写入,影响了查询的效率。

a、读写分离的好处

1)      增加冗余

2)      增加了机器的处理能力

3)      对于读操作为主的应用,使用读写分离是最好的场景,因为可以确保写的服务器压力更小,而读又可以接受点时间上的延迟。

b、读写分离提高性能之原因

1)     物理服务器增加,负荷增加

2)     主从只负责各自的写和读,极大程度的缓解X锁和S锁争用

3)     从库同步主库的数据和主库直接写还是有区别的,通过主库发送来的binlog恢复数据,但是,最重要区别在于主库向从库发送binlog是异步的,从库恢复数据也是异步的

4)     读写分离适用与读远大于写的场景,如果只有一台服务器,当select很多时,updatedelete会被这些select访问中的数据堵塞,等待select结束,并发性能不高。 对于写和读比例相近的应用,应该部署双主相互复制

5)     可以在从库启动是增加一些参数来提高其读的性能,当然这些设置也是需要根据具体业务需求来定得,不一定能用上

6)     分摊读取。假如我们有13从,不考虑上述1中提到的从库单方面设置,假设现在1 分钟内有10条写入,150条读取。那么,13从相当于共计40条写入,而读取总数没变,因此平均下来每台服务器承担了10条写入和50条读取(主库不 承担读取操作)。因此,虽然写入没变,但是读取大大分摊了,提高了系统性能。另外,当读取被分摊后,又间接提高了写入的性能。所以,总体性能提高了,说白了就是拿机器和带宽换性能。

7)     复制另外一大功能是增加冗余,提高可用性,当一台数据库服务器宕机后能通过调整另外一台从库来以最快的速度恢复服务,因此不能光看性能,也就是说11从也是可以的。

三、 ORACLE读写分离的方式,各有优缺点?

        读写分离的重点其实就是数据同步,能实现数据实时同步的技术很多,基于OS(例如VERITAS VVR),基于存储复制(中高端存储大多都支持),基于应用分发或者基于数据库层的技术。因为数据同步可能并不是单一的DB整库同步,会涉及到业务数据选择以及多源整合等问题,因此OS复制和存储复制多数情况并不适合做读写分离的技术首选。

        基于日志的Oracle复制技术,Oracle自身组件可以实现,同时也有成熟的商业软件。选商业的独立产品还是Oracle自身的组件功能,这取决于多方面的因素。比如团队的相应技术运维能力、项目投入成本、业务系统的负载程度等。

a、主从同步

a.1、采用Oracle自身组件功能

        无外乎Logical StandbyStream以及11gPhysical Standby(Active Data Guard),对比来说,Stream最灵活,但最不稳定,11g Physical Standby支持恢复与只读并行,但由于并不是日志的逻辑应用机制,在读写分离的场景中最为局限。如果技术团队对相关技术掌握足够充分,而选型方案的处理能力又能支撑数据同步的要求,采用Oracle自身的组件完全可行。

a.1.1DG方案

        DG方案也叫ADG方案,英语全称Physical Standby(Active DataGuard)。支持恢复与只读并行,但由于并不是日志的逻辑应用机制,在读写分离的场景中最为局限 ,将生产机的logfiles传递给容灾机,通过Redo Apply技术来保障数据镜像能力,物理上提供了与生产数据库在数据块级的一致性镜像,也叫physical方式。Physical方式支持异步传输方式,但容灾机处在恢复状态,不可用;

a.1.2Logical Standby

        通过SQL Apply(即Log Miner)技术,将接收到的日志文件还原成SQL语句,并在逻辑备份数据库上执行,从而达到数据一致性的目的,也叫logical 方式。logical方式只支持同步传输方式,但容灾机可以处在read-only状态

a.1.3Stream

        最灵活,但最不稳定

a.2、选择商业化的产品

        更多出于稳定性、处理能力等考虑。市面上成熟的Oracle复制软件也无外乎几种,无论是老牌的Shareplex,还是本土DSG公司的RealSync和九桥公司的DDS,或是Oracle新贵GoldenGate,都是可供选择的目标。随着GoldenGateOracle收购和推广,个人认为GoldenGate在容灾、数据分发和同步方面将大行其道。

b、读写分离

b.1、数据库中间键mycat 实现oracle数据库读写分离

b.1.1、下载mycat

wget https://github.com/MyCATApache/Mycat-download/blob/master/1.4-RELEASE/Mycat-server-1.4-release-20151019230038-linux.tar.gz 

b.1.2、解压

tar -zxvf Mycat-server-1.4-release-20151019230038-linux.tar.gz 

b.1.3、配置环境变量:

vi /etc/profile 

末尾加上

MYCAT_HOME=/MyCat/mycat    //mycat安装路径

PATH=$PATH:$MYCAT_HOME/bin 

export MYCAT_HOME PATH 

b.1.4、修改配置文件

/MyCat/mycat/conf/wrapper.conf

修改

wrapper.java.command= /usr/java/jdk1.7.0_80/bin/java  //修改wrapper.java.command jdkbin目录下的java

b.1.5、设置mycat用户名和密码

修改配置文件/MyCat/mycat/conf/server.xml

<user name="root"> //用户名和密码随意设置 

    <property name="password">root</property> 

    <property name="schemas">ORACLEDB</property>//schemas对应schema.xml中的schema 

</user>   

<user name="admin"> 

    <property name="password">admin</property> 

    <property name="schemas">ORACLEDB</property> 

    <property name="readOnly">true</property> 

</user> 

b.1.6、修改配置文件/MyCat/mycat/conf/schema.xml

<?xml version="1.0"?> 

<!DOCTYPE mycat:schema SYSTEM "schema.dtd"> 

<mycat:schema xmlns:mycat="http://org.opencloudb/"> 

  <schema name="ORACLEDB" checkSQLschema="false" dataNode="dn1">  // 

  </schema> 

  <dataNode name="dn1" dataHost="localhost1" database="db1" />

<!—database表空间名称 -->

  <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="oracle" dbDriver="jdbc"

    <heartbeat>select 1 from dual</heartbeat> 

    <writeHost host="hostM1" url="jdbc:oracle:thin:@10.16.13.23:1521/orcl" user="test_user" password="test_user" >   //写入的数据库

    <readHost host="hostS1" url="jdbc:oracle:thin:@10.16.12.9:1521/orcl" user="strmadmin" password="strmadmin"/>  //读取的数据库

    </writeHost> 

  </dataHost> 

</mycat:schema> 

配置结束

b.1.7、启动mycat

mycat start 

可以查看日志文件看是否报错/MyCat/mycat/logs/mycat.log

启动报错,导入ojdbc7mycatlib目录下


 

b.1.8、测试

        navicat客户端连接mycat (ipmycat所在的服务器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 #重启防火墙使配置生效

b.1.9、程序中配置如下

<hibernate-configuration> 

    <session-factory> 

        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> //驱动 我测试的mysql oracle貌似都可以 

        <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property> 

        <!-- 

        <property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property> 

        <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property> --> 

        <property name="hibernate.connection.password">root</property> 

    <property name="hibernate.connection.url">jdbc:mysql://10.16.1.2:8066/ORACLEDB</property> //这你没看错 就是mysql ,换成oracle是不可以的 

        <property name="hibernate.connection.username">root</property> 

     

         

    <property name="hibernate.format_sql">true</property> 

        <property name="hibernate.hbm2ddl.auto">update</property> 

         

        <mapping resource="org/crazyit/app/domain/Customer.hbm.xml"/> 

                        

    </session-factory> 

</hibernate-configuration> 

b.1.10、相关命令

关闭mycat    mycat stop

查看mycat状态 mycat status

 

 

四、 ADG

a、软件环境准备

        2oracle数据库服务器,做单例数据库的读写分离。安装配置略

        2rac数据库服务器。做集群环境的读写分离。安装配置略

b、安装配置前检查

        单例数据库的读写分离,检测2oracle服务器宿主机是否安装oracle数据库,是否配置和版本等等一致。安装配置略

        Rac集群数据库的读写分离,分别检测2rac集群数据库是环境配置、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

 

 

c、安装配置

        注意:主库需要建好库(执行dbca),备库不需要。

c.1、将数据库改为强制日志模式  (主库)         

                [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

 

c.2、创建密码文件 (主库)

注意:两端分别创建自己的密码文件好像有问题,备库的密码文件需要跟主库一致,否则导致日志传输不到备库,有待验证。我最后是将主库的密码文件直接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

c.3、创建standby redolog日志组   (主库)

注意:standby redo log的文件大小与primary 数据库online redo log 文件大小相同。standby redo log日志文件组的个数依照下面的原则进行计算:Standby redo log组数公式>=(每个instance日志组个数+1)*instance个数,假如只有一个节点,这个节点有三组redolog,所以Standby redo log组数>=(3+1)*1 == 4,所以至少需要创建4Standby 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所以至少需要创建4Standby 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

c.4、修改主库的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创建一个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主数据库SIDstd备份数据库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

c.5、用修改过的pfile重新创建一个spfile用于重启数据库(主库)

                关闭数据库:

                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

c.6、修改监听文件,添加静态监听       (主库、备库都要做)

主库:

[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

如上,静态监听添加成功

c.7、编辑网络服务名配置文件tnsnames.ora       (主库和备库端都要做)

[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

c.8、在备库端,修改pfile参数文件        (备库)

首先,在主库端把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的区别

c.9、在备库端手工创建所需的目录   (备库,不提前创建的话恢复时会报错!)

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

c.10、用修改后的pfile创建一个spfile,用于启动数据库       (备库)

[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

c.11、利用RMAN在备库上恢复主库            (备库)

[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

恢复数据库结束

c.12、尝试开启备库

        登陆并查看数据库当前状态:

        [oracle@std ~]$ sqlplus / as sysdba

                SYS@std>startup

                SYS@std>select status from v$instance;

STATUS

------------

MOUNTED        RMAN恢复完直接就是mount状态)

c.13、备库启动日志应用(启用备库前确认归档日志是否都已拷贝)

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;命令来进行日志切换,再到备库查看日志应用情况

c.14、分别查看主库和备库的归档序列号是否一致:

先在主库手动切换一下日志:

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的搭建成功!

d、完成后检测

d.1、查看standby启动的DG进程

        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. 

d.2、查看数据库的保护模式:

        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; 

d.3Open Read Onlystandby数据库并且开启实时日志应用

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锁时,其他事务只能再对数据AS锁,而不能加X锁,直到T释放A上的S锁,若事务T对数据对象A加了S锁,则T就可以对A进行读取,但不能进行更新(S锁因此又称为读锁),在T释放A上的S锁以前,其他事务可以再对AS锁,但不能加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",所有写操作都随机的发送到配置的 writeHostwriteType="2",没实现。不写入switchType 属性,mysql挂了,mysql是否提升为主,-1 表示不自动切换,1 默认值,自动切换,2 基于MySQL主从同步的状态决定是否切换

  • 16
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Java代码中实现Oracle读写分离可以使用数据库连接池技术,并在连接池中配置读写分离的规则。以下是一些实现方法: 1. 使用第三方的连接池工具,如C3P0、DBCP和BoneCP等,这些连接池工具都支持读写分离的配置。 2. 在代码中手动实现读写分离的逻辑,即根据SQL语句的类型自动选择读写数据库连接。可以使用JDBC的Connection接口中的setReadOnly()方法来设置连接只读或读写。例如: ``` Connection conn = dataSource.getConnection(); Statement stmt = conn.createStatement(); if (isSelectQuery(sql)) { conn.setReadOnly(true); } else { conn.setReadOnly(false); } ResultSet rs = stmt.executeQuery(sql); ``` 其中 `isSelectQuery()` 方法用于判断当前 SQL 语句是否是读操作。 3. 使用ORM框架,如Hibernate和MyBatis等,这些框架都支持在配置文件中配置读写分离的规则。例如,在MyBatis的配置文件中可以通过配置多个数据源来实现读写分离: ``` <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL_RW"/> <property name="username" value="rwuser"/> <property name="password" value="rwpassword"/> </dataSource> <dataSource type="POOLED"> <property name="driver" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL_RO"/> <property name="username" value="rouser"/> <property name="password" value="ropassword"/> <property name="readOnly" value="true"/> </dataSource> </environment> </environments> ``` 其中 `ORCL_RW` 和 `ORCL_RO` 分别是读写和只读数据库的连接字符串。在代码中使用时,只需指定相应的环境即可: ``` SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream, "development"); SqlSession session = sessionFactory.openSession(); ``` 以上是一些实现Oracle读写分离的方法,具体实现可根据实际情况选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值