您的位置:首页 > 数据库 > Oracle

Oracle 9i & 10g编程艺术-深入数据库体系结构——第2章:体系结构概述

2008-01-13 17:06 1126 查看

第2章 体系结构概述

Oracle被设计为一个相当可移植的数据库;在当前所有平台上都能运行,从Windows到UNIX再到大型机都支持Oracle。出于这个原因,在不同的操作系统上,Oracle的物理体系结构也有所不同。例如,在UNIX操作系统上可以看到,Oracle实现为多个不同的操作系统进程,实际上每个主要功能分别由一个进程负责。这种实现对于UNIX来说是正确的,因为UNIX就是以多进程为基础。不过,如果放到Windows上就不合适了,这种体系结构将不能很好地工作(速度会很慢,而且不可扩缩)。在Windows平台上,Oracle实现为一个多线程的进程。如果是一个运行OS/390和z/OS的IBM大型机系统,针对这种操作系统的Oracle体系结构则充分利用了多个OS/390地址空间,它们都作为一个Oracle实例进行操作。一个数据库实例可以配置多达255个地址空间。另外,Oracle还能与OS/390 工作负载管理器(Workload Manager,WLM)协作,建立特定Oracle工作负载相互之间的相对执行优先级,还能建立相对于OS/390系统中所有其他工作的执行优先级。尽管不同平台上实现Oracle所用的物理机制存在变化,但Oracle体系结构还是很有一般性,所以你能很好地了解Oracle在所有平台上如何工作。
这一章会从全局角度概要介绍这个体系结构。我们会分析Oracle服务器,并给出“数据库”和“实例”等术语的定义(这些术语通常很容易混淆)。这里还会介绍“连接”到Oracle时会发生什么,另外将从高层分析服务器如何管理内存。在后续3章中,我们还会详细介绍Oracle体系结构中的3大部分:
q 第3章将介绍文件,其中涵盖构成数据库的5大类文件:参数文件、数据文件、临时文件、控制文件和重做日志文件。我们还会介绍另外几类文件,包括跟踪文件、警告文件、转储文件(DMP)、数据泵文件(data pump)和简单的平面文件。这一章将谈到Oracle 10g 新增的一个文件区,称为闪回恢复区(Flashback Recovery Area),另外我们还会讨论自动存储管理(Automatic Storage Management,ASM)对文件存储的影响。
q 第4章介绍Oracle的一些内存结构,分别称为系统全局区(System Global Area,SGA)、进程全局区(Process Global Area,PGA)和用户全局区(User Global Area,UGA)。我们会分析这些结构之间的关系,并讨论共享池(shared pool)、大池(big pool)、Java池(Java pool)以及SGA中的其他一些组件。
q 第5章介绍Oracle的物理进程或线程。我们会讨论数据库上运行的3类不同的进程:服务器进程(server process)、后台进程(background process)和从属进程(slave process)。
先介绍哪一部分实在很难定夺。由于进程使用了SGA,所以如果在进程之前先介绍SGA可能不太合适。另一方面,讨论进程及其工作时,又会引用SGA。另外两部分的关系也很紧密:文件由进程处理,如果不先了解进程做什么,将很难把文件搞清楚。
正因如此,我会在这一章定义一些术语,对Oracle是什么提供一个一般性的概述(也许你会把它画出来)。有了这些准备,你就能深入探访各个部分的具体细节了。

2.1 定义数据库和实例

在Oracle领域中有两个词很容易混淆,这就是“实例”(instance)和“数据库”(database)。作为Oracle术语,这两个词的定义如下:
q 数据库(database):物理操作系统文件或磁盘(disk)的集合。使用Oracle 10g的自动存储管理(Automatic Storage Management,ASM)或RAW分区时,数据库可能不作为操作系统中单独的文件,但定义仍然不变。
q 实例(instance):一组Oracle后台进程/线程以及一个共享内存区,这些内存由同一个计算机上运行的线程/进程所共享。这里可以维护易失的、非持久性内容(有些可以刷新输出到磁盘)。就算没有磁盘存储,数据库实例也能存在。也许实例不能算是世界上最有用的事物,不过你完全可以把它想成是最有用的事物,这有助于对实例和数据库划清界线。
这两个词有时可互换使用,不过二者的概念完全不同。实例和数据库之间的关系是:数据库可以由多个实例装载和打开,而实例可以在任何时间点装载和打开一个数据库。实际上,准确地讲,实例在其整个生存期中最多能装载和打开一个数据库!稍后就会介绍这样的一个例子。
是不是更糊涂了?我们还会做进一步的解释,应该能帮助你搞清楚这些概念。实例就是一组操作系统进程(或者是一个多线程的进程)以及一些内存。这些进程可以操作数据库;而数据库只是一个文件集合(包括数据文件、临时文件、重做日志文件和控制文件)。在任何时刻,一个实例只能有一组相关的文件(与一个数据库关联)。大多数情况下,反过来也成立:一个数据库上只有一个实例对其进行操作。不过,Oracle的真正应用集群(Real Application Clusters,RAC)是一个例外,这是Oracle提供的一个选项,允许在集群环境中的多台计算机上操作,这样就可以有多台实例同时装载并打开一个数据库(位于一组共享物理磁盘上)。由此,我们可以同时从多台不同的计算机访问这个数据库。Oracle RAC能支持高度可用的系统,可用于构建可扩缩性极好的解决方案。
下面来看一个简单的例子。假设我们刚安装了Oracle 10g 10.1.0.3。我们执行一个纯软件安装,不包括初始的“启动”数据库,除了软件以外什么都没有。
通过pwd命令可以知道当前的工作目录(这个例子使用一个Linux平台的计算机)。我们的当前目录是dbs(如果在Windows平台上,则是database目录)。执行ls–l命令显示出这个目录为“空”。其中没有init.ora 文件,也没有任何存储参数文件(stored parameter file,SPFILE);存储参数文件将在第3章详细讨论。
[ora10g@localhost dbs]$ pwd
/home/ora10g/dbs
[ora10g@localhost dbs]$ ls -l
total 0
使用ps(进程状态)命令,可以看到用户ora10g运行的所有进程,这里假设ora10g是Oracle软件的所有者。此时还没有任何Oracle数据库进程。
[ora10g@localhost dbs]$ ps -aef | grep ora10g
ora10g 4173 4151 0 13:33 pts/0 00:00:00 -su
ora10g 4365 4173 0 14:09 pts/0 00:00:00 ps -aef
ora10g 4366 4173 0 14:09 pts/0 00:00:00 grep ora10g
然后使用ipcs命令,这个UNIX命令可用于显示进程间的通信设备,如共享内存、信号量等。目前系统中没有使用任何通信设备。
[ora10g@localhost dbs]$ ipcs -a
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status

------ Semaphore Arrays --------
key semid owner perms nsems

------ Message Queues --------
key msqid owner perms used-bytes messages
然后启动SQL*Plus(Oracle的命令行界面),并作为SYSDBA连接(SYSDBA账户可以在数据库中做任何事情)。连接成功后,SQL*Plus报告称我们连上了一个空闲的实例:
[ora10g@localhost dbs]$ sqlplus "/ as sysdba"
SQL*Plus: Release 10.1.0.3.0 - Production on Sun Dec 19 14:09:44 2004
Copyright (c) 1982, 2004, Oracle. All rights reserved.
Connected to an idle instance.
SQL>
我们的“实例”现在只包括一个Oracle服务器进程,见以下输出中粗体显示的部分。此时还没有分配共享内存,也没有其他进程。
SQL> !ps -aef | grep ora10g
ora10g 4173 4151 0 13:33 pts/0 00:00:00 -su
ora10g 4368 4173 0 14:09 pts/0 00:00:00 sqlplus as sysdba
ora10g 4370 1 0 14:09 ? 00:00:00 oracleora10g (...)
ora10g 4380 4368 0 14:14 pts/0 00:00:00 /bin/bash -c ps -aef | grep ora10g
ora10g 4381 4380 0 14:14 pts/0 00:00:00 ps -aef
ora10g 4382 4380 0 14:14 pts/0 00:00:00 grep ora10g

SQL> !ipcs -a

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status

------ Semaphore Arrays --------
key semid owner perms nsems

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

SQL>
现在来启动实例:
SQL> startup
ORA-01078: failure in processing system parameters
LRM-00109: could not open parameter file '/home/ora10g/dbs/initora10g.ora'
SQL>
这里提示的文件就是启动实例时必须要有的一个文件,我们需要有一个参数文件(一种简单的平面文件,后面还会详细说明),或者要有一个存储参数文件。现在就来创建参数文件,并放入启动数据库实例所需的最少信息(通常还会指定更多的参数,如数据库块大小、控制文件位置,等等)。
$ cat initora10g.ora
db_name = ora10g
然后再回到SQL*Plus:
SQL> startup nomount
ORACLE instance started.
这里对startup命令加了nomount选项,因为我们现在还不想真正“装载”数据库(要了解启动和关闭的所有选项,请参见SQL*Plus文档)。

注意 在Windows上运行startup命令之前,还需要使用oradim.exe实用程序执行一条服务创建语句。

现在就有了所谓的“实例”。运行数据库所需的后台进程都有了,如进程监视器(process monitor,PMON)、日志写入器(log writer,LGWR)等,这些进程将在第5章详细介绍。
Total System Global Area 113246208 bytes
Fixed Size 777952 bytes
Variable Size 61874464 bytes
Database Buffers 50331648 bytes
Redo Buffers 262144 bytes
SQL> !ps -aef | grep ora10g
ora10g 4173 4151 0 13:33 pts/0 00:00:00 -su
ora10g 4368 4173 0 14:09 pts/0 00:00:00 sqlplus as sysdba
ora10g 4404 1 0 14:18 ? 00:00:00 ora_pmon_ora10g
ora10g 4406 1 0 14:18 ? 00:00:00 ora_mman_ora10g
ora10g 4408 1 0 14:18 ? 00:00:00 ora_dbw0_ora10g
ora10g 4410 1 0 14:18 ? 00:00:00 ora_lgwr_ora10g
ora10g 4412 1 0 14:18 ? 00:00:00 ora_ckpt_ora10g
ora10g 4414 1 0 14:18 ? 00:00:00 ora_smon_ora10g
ora10g 4416 1 0 14:18 ? 00:00:00 ora_reco_ora10g
ora10g 4418 1 0 14:18 ? 00:00:00 oracleora10g (...)
ora10g 4419 4368 0 14:18 pts/0 00:00:00 /bin/bash -c ps -aef | grep ora10g
ora10g 4420 4419 0 14:18 pts/0 00:00:00 ps -aef
ora10g 4421 4419 0 14:18 pts/0 00:00:00 grep ora10g
再使用ipcs命令,它会首次报告指出使用了共享内存和信号量,这是UNIX上的两个重要的进程间通信设备:
SQL> !ipcs –a

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x99875060 458760 ora10g 660 115343360 8

------ Semaphore Arrays --------
key semid owner perms nsems
0xf182650c 884736 ora10g 660 34

------ Message Queues --------
key msqid owner perms used-bytes messages
SQL>
注意,我们还没有“数据库”呢!此时,只有数据库之名(在所创建的参数文件中),而没有数据库之实。如果试图“装载”这个数据库,就会失败,因为数据库根本就不存在。下面就来创建数据库。有人说创建一个Oracle数据库步骤很繁琐,真是这样吗?我们来看看:
SQL> create database;
Database created.
这里创建数据库就是这么简单。但在实际中,也许要使用一个稍有些复杂的CREATE DATABASE命令,因为可能需要告诉Oracle把日志文件、数据文件、控制文件等放在哪里。不过,我们现在已经有了一个完全可操作的数据库了。可能还需要运行$ORACLE_HOME/rdbms/admin/ catalog.sql脚本和其他编录脚本(catalog script)来建立我们每天使用的数据字典(这个数据库中还没有我们使用的某些视图,如ALL_OBJECTS),但不管怎么说,数据库已经有了。可以简单地查询一些Oracle V$视图(具体就是V$DATAFILE、V$LOGFILE和V$CONTROLFILE),列出构成这个数据库的文件:
SQL> select name from v$datafile;

NAME
--------------------------------------------------------------------------------
/home/ora10g/dbs/dbs1ora10g.dbf
/home/ora10g/dbs/dbx1ora10g.dbf

SQL> select member from v$logfile;

MEMBER
--------------------------------------------------------------------------------
/home/ora10g/dbs/log1ora10g.dbf
/home/ora10g/dbs/log2ora10g.dbf

SQL> select name from v$controlfile;

NAME
--------------------------------------------------------------------------------
/home/ora10g/dbs/cntrlora10g.dbf

SQL>
Oracle使用默认设置,把所有内容都放在一起,并把数据库创建为一组持久的文件。如果关闭这个数据库,再试图打开,就会发现数据库无法打开:
SQL> alter database close;
Database altered.
SQL> alter database open;
alter database open
*
ERROR at line 1:
ORA-16196: database has been previously opened and closed
一个实例在其生存期中最多只能装载和打开一个数据库。要想再打开这个(或其他)数据库,必须先丢弃这个实例,并创建一个新的实例。
重申一遍:
q 实例是一组后台进程和共享内存。
q 数据库是磁盘上存储的数据集合。
q 实例“一生”只能装载并打开一个数据库。
q 数据库可以由一个或多个实例(使用RAC)装载和打开。
前面提到过,大多数情况下,实例和数据库之间存在一种一对一的关系。可能正因如此,才导致人们很容易将二者混淆。从大多数人的经验看来,数据库就是实例,实例就是数据库。
不过,在许多测试环境中,情况并非如此。在我的磁盘上,可以有5个不同的数据库。测试主机上任意时间点只会运行一个Oracle实例,但是它访问的数据库每天都可能不同(甚至每小时都不同),这取决于我的需求。只需有不同的配置文件,我就能装载并打开其中任意一个数据库。在这种情况下,任何时刻我都只有一个“实例”,但有多个数据库,在任意时间点上只能访问其中的一个数据库。
所以,你现在应该知道,如果有人谈到实例,他指的就是Oracle的进程和内存。提到数据库时,则是说保存数据的物理文件。可以从多个实例访问一个数据库,但是一个实例一次只能访问一个数据库。

2.2 SGA和后台进程

你可能已经想到了Oracle实例和数据库的抽象图是个什么样子(见图2-1)。
图2-1以最简单的形式展示了Oracle实例和数据库。Oracle有一个很大的内存块,称为系统全局区(SGA),在这里它会做以下工作:
q 维护所有进程需要访问的多种内部数据结构;
q 缓存磁盘上的数据,另外重做数据写至磁盘之前先在这里缓存;
q 保存已解析的SQL计划;
q 等等。



图2-1 Oracle实例和数据库
Oracle有一组“附加到”SGA的进程,附加机制因操作系统而异。在UNIX环境中,这些进程会物理地附加到一个很大的共享内存段,这是操作系统中分配的一个内存块,可以由多个进程并发地访问(通常要使用shmget()和shmat())。
在Windows中,这些进程只是使用C调用(malloc())来分配内存,因为它们实际上是一个大进程中的线程,所以会共享相同的虚拟内存空间。Oracle还有一组供数据库进程/线程读写的文件(只允许Oracle进程读写这些文件)。这些文件保存了所有的表数据、索引、临时空间、重做日志等。
如果在一个UNIX系统上启动Oracle,并执行ps命令,会看到运行着许多物理进程,还会显示出这些进程的名字。在前面的例子中,我们已经观察到了pmon、smon以及其他一些进程。我会在第5章逐一介绍这些进程,现在只要知道它们通称为Oracle后台进程(background process)就足够了。这些后台进程是构成实例的持久性进程,从启动实例开始,这些进程会一直运行,直至实例关闭。
有一点要注意,这些都是进程,而不是单个的程序。UNIX上只有一个Oracle二进制可执行文件;根据启动时所提供的选项,这个可执行文件会有多种不同的“个性”。执行ora_pmon_ora10g进程要运行这个二进制可执行文件,执行ora_ckpt_ora10g进程时运行的可执行文件仍是它。二进制可执行文件只有一个,就是oracle,只是会以不同的名字执行多次。
在Windows上,使用pslist工具(http://www.sysinternals.com/ntw2k/freeware/ pslist.shtml)只会看到一个进程oracle.exe。同样,Windows上也只有一个二进制可执行文件(oracle.exe)。在这个进程中,可以看到表示Oracle后台进程的多个线程。
使用pslist(或另外的某个工具),可以看到以下线程:
C:/Documents and Settings/tkyte>pslist oracle

PsList 1.26 - Process Information Lister
Copyright (C) 1999-2004 Mark Russinovich
Sysinternals - www.sysinternals.com

Process information for ORACLE-N15577HE:

Name Pid Pri Thd Hnd Priv CPU Time Elapsed Time
oracle 1664 8 19 284 354684 0:00:05. 687 0:02:42.218
从中可以看出,这个Oracle进程里有19个线程(以上所示的Thd列)。这些线程就对应于UNIX上的进程(pmon、arch、lgwr等Oracle进程)。还可以用pslist查看各线程的更多详细信息:
C:/Documents and Settings/tkyte>pslist -d oracle
PsList 1.26 - Process Information Lister
Copyright (C) 1999-2004 Mark Russinovich
Sysinternals - www.sysinternals.com
Thread detail for ORACLE-N15577HE:
oracle 1664:

Tid Pri Cswtch State User Time KernelTime Elapsed Time
1724 9 148 Wait:Executive 0:00:00.000 0:00:00.218 0:02:46.625
756 9 236 Wait:UserReq 0:00:00.000 0:00:00.046 0:02:45.984
1880 8 2 Wait:UserReq 0:00:00.000 0:00:00.000 0:02:45.953
1488 8 403 Wait:UserReq 0:00:00.000 0:00:00.109 0:02:10.593
1512 8 149 Wait:UserReq 0:00:00.000 0:00:00.046 0:02:09.171
1264 8 254 Wait:UserReq 0:00:00.000 0:00:00.062 0:02:09.140
960 9 425 Wait:UserReq 0:00:00.000 0:00:00.125 0:02:09.078
2008 9 341 Wait:UserReq 0:00:00.000 0:00:00.093 0:02:09.062
1504 8 1176 Wait:UserReq 0:00:00.046 0:00:00.218 0:02:09.015
1464 8 97 Wait:UserReq 0:00:00.000 0:00:00.031 0:02:09.000
1420 8 171 Wait:UserReq 0:00:00.015 0:00:00.093 0:02:08.984
1588 8 131 Wait:UserReq 0:00:00.000 0:00:00.046 0:02:08.890
1600 8 61 Wait:UserReq 0:00:00.000 0:00:00.046 0:02:08.796
1608 9 5 Wait:Queue 0:00:00.000 0:00:00.000 0:02:01.953
2080 8 84 Wait:UserReq 0:00:00.015 0:00:00.046 0:01:33.468
2088 8 127 Wait:UserReq 0:00:00.000 0:00:00.046 0:01:15.968
2092 8 110 Wait:UserReq 0:00:00.000 0:00:00.015 0:01:14.687
2144 8 115 Wait:UserReq 0:00:00.015 0:00:00.171 0:01:12.421
2148 9 803 Wait:UserReq 0:00:00.093 0:00:00.859 0:01:09.718
不同于UNIX,这里看不到线程的“名字”(UNIX上则会显示ora_pmon_ora10g等进程名),不过,我们可以看到线程ID(Tid),优先级(Pri)以及有关的其他操作系统审计信息。

2.3 连接Oracle

这一节将介绍Oracle服务器处理请求的两种最常见的方式,并分析它们的基本原理,这两种方式分别是专用服务器(dedicated server)连接和共享服务器(shared server)连接。要想登录数据库并在数据库中真正做事情,必须先连接,我们会说明建立连接时客户端和服务器端会发生什么。最后会简要地介绍如何建立TCP/IP连接(TCP/IP是网络上连接Oracle所用的主要网络协议),并说明对于专用服务器连接和共享服务器连接,服务器上的监听器(listener)进程会以不同的方式工作,这些监听器进程负责建立与服务器的物理连接。

2.3.1 专用服务器

从图2-1和pslist输出可以看出启动Oracle之后是什么样子。如果现在使用一个专用服务器登录数据库,则会创建一个新的进程,提供专门的服务:
C:/Documents and Settings/tkyte>sqlplus tkyte/tkyte
SQL*Plus: Release 10.1.0.3.0 - Production on Sun Dec 19 15:41:53 2004
Copyright (c) 1982, 2004, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Production
With the Partitioning, OLAP and Data Mining options

tkyte@ORA10G> host pslist oracle
PsList 1.26 - Process Information Lister
Copyright (C) 1999-2004 Mark Russinovich
Sysinternals - www.sysinternals.com
Process information for ORACLE-N15577HE:

Name Pid Pri Thd Hnd Priv CPU Time Elapsed Time
oracle 1664 8 20 297 356020 0:00:05.906 0:03:21.546
tkyte@ORA10G>
现在可以看到,线程有20个而不是19个,多加的这个线程就是我们的专用服务器进程(稍后会介绍专用服务器进程的更多内容)。注销时,这个额外的线程也没有了。在UNIX上,可以看到正在运行的Oracle进程列表上会多加一个进程,这就是我们的专用服务器。
再回过来看前面的那个图。现在如果按最常用的配置连接Oracle,则如图2-2所示。



图2-2 典型的专用服务器配置
如前所述,在我登录时,Oracle总会为我创建一个新的进程。这通常称为专用服务器配置,因为这个服务器进程会在我的会话生存期中专门为我服务。对于每个会话,都会出现一个新的专用服务器,会话与专用服务器之间存在一对一的映射。按照定义,这个专用服务器不是实例的一部分。我的客户进程(也就是想要连接数据库的程序)会通过某种网络通道(如TCP/IP socket)与这个专用服务器直接通信,并由这个服务器进程接收和执行我的SQL。如果必要,它会读取数据文件,并在数据库的缓存中查找我要的数据。也许它会完成我的更新语句,也可能会运行我的PL/SQL代码。这个服务器进程的主要目标就是对我提交的SQL调用做出响应。

2.3.2 共享服务器

Oracle还可以接受另一种方式的连接,这称为共享服务器(shared server),正式的说法是多线程服务器(Multi-Threaded Server)或MTS。如果采用这种方式,就不会对每条用户连接创建另外的线程或新的UNIX进程。在共享服务器中,Oracle使用一个“共享进程”池为大量用户提供服务。共享服务器实际上就是一种连接池机制。利用共享服务器,我们不必为10,000个数据库会话创建10,000个专用服务器(这样进程或线程就太多了),而只需建立很少的一部分进程/线程,顾名思义,这些进程/线程将由所有会话共享。这样Oracle就能让更多的用户与数据库连接,否则很难连接更多用户。如果让我的机器管理10,000个进程,这个负载肯定会把它压垮,但是管理100个或者1,000个进程还是可以的。采用共享服务器模式,共享进程通常与数据库一同启动,使用ps命令可以看到这个进程。
共享服务器连接和专用服务器连接之间有一个重大区别,与数据库连接的客户进程不会与共享服务器直接通信,但专用服务器则不然,客户进程会与专用服务器直接通信。之所以不能与共享服务器直接对话,原因就在于这个服务器进程是共享的。为了共享这些进程,还需要另外一种机制,通过这种机制才能与服务器进程“对话”。为此,Oracle使用了一个或一组称为调度器(dispatcher,也称分派器)的进程。客户进程通过网络与一个调度器进程通信。这个调度器进程将客户的请求放入SGA中的请求队列(这也是SGA的用途之一)。第一个空闲的共享服务器会得到这个请求,并进行处理(例如,请求可能是UPDATE T SET X = X+5 WHERE Y = 2)。完成这个命令后,共享服务器会把响应放在原调度器(即接收请求的调度器)的响应队列中。调度器进程一直在监听这个队列,发现有结果后,就会把结果传给客户。从概念上讲,共享服务器请求的流程如图2-3所示。



图2-3 共享服务器请求的流程步骤
如图2-3所示,客户连接向调度器发送一个请求。调度器首先将这个请求放在SGA中的请求队列中①。第一个可用的共享服务器从请求队列中取出这个请求②并处理。共享服务器的处理结束后,再把响应(返回码、数据等)放到响应队列中③,接下来调度器拿到这个响应④,传回给客户。
在开发人员看来,共享服务器连接和专用服务器连接之间并没有什么区别。
既然已经了解了专用服务器连接和共享服务器连接是什么,你可能会有一些疑问:
q 首先怎么才能连接呢?
q 谁来启动这个专用服务器?
q 怎么与调度器联系?
这些问题的答案取决于你的特定平台,不过下一节会概括介绍一般的过程。

2.3.3 TCP/IP连接的基本原理

这里将分析网络上最常见的一种情形:在TCP/IP连接上建立一个基于网络的连接请求。在这种情况下,客户在一台机器上,而服务器驻留在另一台机器上,这两台机器通过一个TCP/IP网络连接。客户率先行动,使用Oracle客户软件(Oracle提供的一组应用程序接口,或API)建立一个请求,力图连接数据库。例如,客户可以发出以下命令:
[tkyte@localhost tkyte]$ sqlplus scott/tiger@ora10g.localdomain

SQL*Plus: Release 10.1.0.3.0 - Production on Sun Dec 19 16:16:41 2004
Copyright (c) 1982, 2004, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.1.0.3.0 - Production
With the Partitioning, OLAP and Data Mining options

scott@ORA10G>
这里,客户是程序SQL*Plus,scott/tiger为用户名/密码,ora10g.localdomain是一个TNS服务名。TNS代表透明网络底层(Transparent Network Substrate),这是Oracle客户中处理远程连接的“基础”软件,有了它才有可能建立对等通信。TNS连接串告诉Oracle软件如何与远程数据库连接。一般地,你的机器上运行的客户软件会读取一个tnsnames.ora文件。这是一个纯文本的配置文件,通常放在 [ORACLE_HOME]/network/admin 目录下([ORACLE_HOME] 表示Oracle安装目录的完整路径)。如果有以下配置:
ORA10G.LOCALDOMAIN =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost.localdomain)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = ora10g)
)
根据这个配置信息,Oracle客户软件可以把我们使用的TNS连接串ora10g.localdomain映射到某些有用的信息,也就是主机名、该主机上“监听器”进程接受(监听)连接的端口、该主机上所连接数据库的服务名,等等。服务名表示具有公共属性、服务级阈值和优先级的应用组。提供服务的实例数量对应用是透明的,每个数据库实例可以向监听器注册,表示要提供多个服务。所以,服务就映射到物理的数据库实例,并允许DBA为之关联阈值和优先级。
这个串(ora10g.localdomain)还可以用其他方式来解析。例如,可以使用Oracle Internet目录(Oracle Internet Directory,OID),这是一个分布式轻量级目录访问协议(Lightweight Directory Access Protocol,LDAP)服务器,其作用就相当于解析主机名的DNS。不过,tnsnames.ora文件通常只适用于大多数小到中型安装,在这些情况下,这个配置文件的副本不算太多,尚可管理。
既然客户软件知道要连接到哪里,它会与主机名为localhost.localdomain的服务器在端口1521上打开一条TCP/IP socket连接。如果服务器DBA安装并配置了Oracle Net,并且有一个监听器在端口1521上监听连接请求,就会收到这个连接。在网络环境中,我们会在服务器上运行一个称为TNS监听器的进程。就是这个监听器进程能让我们与数据库物理连接。当它收到入站连接请求时,它会使用自己的配置文件检查这个请求,可能会拒绝请求(例如,因为没有这样的数据库,或者可能我们的IP地址受到限制,不允许连接这个主机),也可能会接受请求,并真正建立连接。
如果建立一条专用服务器连接,监听器进程就会为我们创建一个专用服务器。在UNIX上,这是通过fork()和exec()系统调用做到的(在UNIX中,要在初始化之后创建新进程,惟一的办法就是通过fork())。这个新的专用服务器进程继承了监听器建立的连接,现在就与数据库物理地连接上了。在Windows上,监听器进程请求数据库进程为连接创建一个新线程。一旦创建了这个线程,客户就会“重定向”到该线程,相应地就能建立物理连接。图2-4显示了UNIX上的监听器进程和专用服务器连接。



图2-4 监听器进程和专用服务器连接
另一方面,如果我们发出共享服务器连接请求,监听器的表现则会有所不同。监听器进程知道实例中运行了哪些调度器。接收到连接请求后,监听器会从可用的调度器池中选择一个调度器进程。监听器会向客户返回连接信息,其中说明了客户如何与调度器进程连接;如果可能的话,还可以把连接“转发”给调度器进程(这依赖于不同的操作系统和数据库版本,不过实际效果是一样的)。监听器发回连接信息后,它的工作就结束了,因为监听器一直在特定主机的特定端口上运行(主机名和端口号大家都知道),而调度器会在服务器上随意指派的端口上接受连接。监听器要知道调度器指定的这些随机端口号,并为我们选择一个调度器。客户再与监听器断开连接,并与调度器直接连接。现在就与数据库有了一个物理连接。这个过程如图2-5所示。



图2-5 监听器进程和共享服务器连接

2.4 小结

以上就是Oracle体系结构的概述。在这一章中,我们给出了“实例”和“数据库”的定义,并且了解了如何通过专用服务器连接或共享服务器连接来连接数据库。图2-6对本章的所有内容做了一个总结,展示了使用共享服务器连接的客户和使用专用服务器连接的客户之间的交互方式。由此还显示出,一个Oracle实例可以同时使用这两类连接(实际上,即使配置为使用共享服务器连接,Oracle数据库也总是支持专用服务器连接)。



图2-6 连接概述
有了以上的介绍,下面就能更深入地了解服务器底层的进程,这些进程做什么,以及进程间如何交互。你也可以看看SGA的内部包含什么,它有什么用途。下一章先来介绍Oracle管理数据所用的不同文件类型,并讨论各种文件类型的作用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐