Oracle 数据库实例与RAC

Oracle 数据库是一种支持高并发的RDBMS系统,因此Oracle也需要解决在大量并发用户下的一致性访问问题。Oracle数据库对外提供的访问方式并不是应用程序直接打开数据文件来操作数据库,而是通过一种TWO-TASK的模式提供服务。在这种架构下,应用无法直接访问数据库,而必须通过一种被称为实例(Instance)的逻辑结构去访问数据库。

1. 数据库实例

官方的说法,实例指的就是操作系统中一系列的进程以及为这些进程所分配的内存块。如果用更容易理解的方式来解释,那就是说Oracle数据库的实例是我们访问Oracle数据库的通道。

在一个数据库实例中,包含了Oracle的共享内存和一系列的后台进程,一个实例在同时只能打开一个数据库,而一个数据库可以同时被多个实例打开,当然了,这种情况就是我们常说的RAC。Oracle数据库的实例必须依赖于某个特定的ORACLE_HOME,启动实例需要的所有的程序和相关的文件(除了数据库外)都包含在$ORACLE_HOME中。除此之外,每个实例都有自己独立的SID。在同一个ORACLE_HOME下,允许启动多个实例,但是这些实例必须拥有不同的SID。另外,一个非RAC的数据库是不允许被多个实例打开的,因为实例mount独立数据库的时候,是以排他的方式进行的。一个RAC的数据库,只允许同一个RAC集群中的多个实例打开,非相同集群的节点是无法打开同一个数据库的。

通过上面的介绍,我们了解了实例、数据库、ORACLE_HOME、SID这些概念之间的关系,下面我们进一步来了解实例。在Oracle中,我们可以启动一个Oracle的实例,这个时候虽然有了进程还有SGA等一系列的内存块,但是并没有把数据库文件读取进来。实例启动后,为访问Oracle数据库的应用提供了一个基础的环境。这个基础环境包含了一组共享内存,后者又包含了Oracle数据库的一系列内部数据结构,也包括了Oracle数据库的SQL和数据字典缓冲(共享池中的库缓存和字典缓存),还有数据块缓冲(DB Cache)。在一个启动了Oracle实例的UNIX系统上,使用ipcs命令可以看到共享内存的情况:

[oracle@dbtest ~]$ ipcs
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status      
0x00000000 5767169    root      644        80         2                       
0x00000000 5799939    root      644        16384      2                       
0x00000000 5832708    root      644        280        2                       
0x00000000 12648454   oracle    660        4096       0                       
0x00000000 12681223   oracle    660        4096       0                       
0x00000000 12713992   oracle    660        4096       0                       
0xd3ac6c80 12746761   oracle    660        4096       0                       

------ Semaphore Arrays --------
key        semid      owner      perms      nsems     
0x5c23a1bc 4128769    oracle    660        154       

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages  

我们可以看到,Oracle用户分配了一组共享内存和信号灯。实例启动时首先会装载参数文件,根据参数文件中定义的内存相关参数创建共享内存和信号灯。根据参数文件,启动进程完成SGA中内存结构的初始化工作,然后启动相关的后台进程。这个过程完成后,数据库实例启动的第一步nomount就完成了。

实例启动到nomount后,所有的共享内存和后台进程就都已经装载完毕。于是,系统根据参数文件中控制文件的位置,打开控制文件,并对控制文件进行校验,如果这个步骤没有发现问题,就完成了mount步骤。

据库实例mount完成后,通过对控制文件、UNDO和REDO等进行比对分析后,发现数据库状态是一致的,数据库实例就可以打开数据库了。数据库打开后,数据库实例就可以提供对外服务了。数据库实例启动后,应用程序就可以通过数据库实例来访问数据库了。

应用要访问Oracle数据库,可以通过三种方式:

第一种方式是应用进程直接访问数据库实例的共享内存
第二种方式是通过beq协议在本机上访问
第三种方式是通过网络协议访问。

第一种方式使用的场合很少,我们不做讨论。下面着重讨论通过第二种和第三种方式访问数据库。首先,后两种访问数据库的方式都是基于two-task结构的,都需要在数据库服务器上建立一个服务进程(server进程,或者前台进程)来为客户端应用服务(在这里我们只讨论独立服务器模式,共享服务器模式十分类似)。two-task架构下访问数据库,首先需要在服务器端创建一个进程,这个进程启动时先要映射共享内存,然后才能够通过共享内存中的内部数据结构完成会话的初始化工作。

在本机上不经过SQL*Net连接数据库,前台进程和用户进程之间通过IPC机制进行通信,通信协议就是著名的Bequeath协议,简称BEQ协议。而如果通过SQL*Net连接数据库,那么就需要使用网络协议。现在TCP/IP协议已经成为使用最为广泛的协议,因此我们主要面对的是TCP/IP协议。使用SQL*Net协议的前台进程和用户进程之间的通信采用Socket通信。实际上,在服务器上,我们也可以使用SQL*Net连接数据库,只不过我们很少会去这样做,因为BEQ协议在效率上高于Socket通信。

2. 多实例数据库RAC

多实例数据库可以说是RAC的另外一种称呼,Oracle RAC的特点就是多个数据库实例可以同时打开相同的数据库,进行并发的操作。多实例数据库是Oracle高可用架构和高可扩展性架构的核心技术,多个实例同时打开数据库进行读写,可以避免某个实例故障导致的系统不可用,同时多实例实现负载分担,也可以减轻某个实例的工作负载,从而提高整体吞吐能力。

Oracle RAC是多实例数据库的正式名称,RAC具有很多激动人心的特性,但是实施RAC也有一些潜在的风险。在实施之前,我们必须认真地了解RAC的一些基本概念。

RAC多实例数据库架构有几个基础。第一个基础是共享存储,多台服务器(一般来说我们称之为节点)可以同时并发读写相同的文件。如果没有这个基础,RAC就无从谈起。我们可以使用很多技术来实现共享存储,最为普遍使用的就是存储局域网络SAN,通过光纤交换机连接的共享存储,一组lun可以同时被多个服务器节点访问。除了SAN外,以NETAPP为代表的基于TCP/IP的存储解决方案也是RAC的可选方案,通过ISCSI或者NFS共享文件系统,同样可以满足RAC对于共享存储的需要。

多实例数据库系统的一个很重要的特性是多个实例可以并发对同一个数据进行读写,这一点也是RAC十分核心的功能。不过在多实例数据库环境中,每个实例都拥有自己独立的SGA,为了确保数据库的一致性,Oracle RAC系统需要使用一个被称为缓冲区融合(CACHE FUSION)的技术来实现多个节点上的缓冲区的一致性访问。因此,在多实例数据库中修改数据,需要一些额外的成本。

多实例数据库的特性对于DBA分析数据库故障,以及进行优化处理都提出了一个新的要求。就是我们在分析某个事件或者问题时,不能局限于某个实例,而要将思路拓宽到所有实例。比如说我们发现某个操作被HANG住时,不仅仅要分析本实例上面可能存在的BLOCKER,而且要将分析的范围扩大到其他所有的实例,才有可能找到问题的根源。

多实例的数据库中,每个实例拥有一组独立的在线日志记录,也就是我们常说的REDO THREAD。每个实例独立生成在线日志信息,并且拥有独立的LGWR进程用于写入在线日志文件。但是在RAC数据库环境中,在线日志文件也必须是所有节点都能够共同访问的。原因也是一样的,当进行实例恢复的时候,由于相关的数据被写在多个在线日志文件中,因此必须用到所有的REDO LOG THREAD中的在线日志文件,才能够完成恢复。当我们在数据库上增加一个新的实例的时候,必须为这个实例创建一组新的在线日志记录,同时激活这个REDO LOG THREAD。反过来,要从数据库中删除一个实例的时候,我们必须关闭这个THREAD,否则无论这个实例是否被使用,数据库恢复的时候,仍然会需要使用这个THREAD的日志。

在使用 UNDO 自动管理的模式下,每个实例都需要使用独立的UNDO表空间,这些表空间的数据文件也必须存放在所有实例都能够访问的共享存储上。

原文地址:https://www.sunansheng.com/blog/20180603/oracle-instance.html