Chinaunix首页 | 论坛 | 博客
  • 博客访问: 436283
  • 博文数量: 119
  • 博客积分: 5221
  • 博客等级: 大校
  • 技术积分: 972
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-04 08:57
文章分类

全部博文(119)

文章存档

2011年(13)

2010年(21)

2009年(19)

2008年(66)

我的朋友

分类: Oracle

2010-04-06 11:55:24

Oracle中SID的作用类似于一个“开关变量”---引导Oracle在实例启动时如何去默认位置下读取适当的参数文件并加载,以正确启动实例。

我们知道实例的启动需要指定pfile/spfile(Oracle9i之前是使用pfile--即init文件,从9i开始就默认使用spfile--即服务器端参数文件,两者的不同请参考《OracleConcept》手册,关键在于修改其中参数后是否会自动持久化)。这两个文件的存放位置为:

A.pfile:名字为init.ora
B.spfile:名字为spfile.ora

我们看到init文件和spfile文件都带有ORACLE_SID的标识,这就是SID的作用了:

【1】当我们要启动一个实例时,我们首先通过:set ORACLE_SID = XXX 或者export ORACLE_SID = XXX 的方式告诉Oracle接下来要启动的实例

【2】当我们执行startup nomount时,由于已经指定了SID,那么Oracle知道了如何去默认的目录下查找该实例对应的参数文件--就是靠SID去匹配每个init/spfile文件

【3】当Oracle找到该文件后(init/spfile),就会读取该文件的内容,将一系列参数用于分配内存空间,构建后台进程等实例的启动过程

【4】当这个实例成功启动后,我们又可以重新执行 set ORACLE_SID = XXX 或 export ORACLE_SID = XXX 命令再次将“开关拨向”另一个SID,然后重复以上步骤

从上面的过程我们看到Oracle SID的作用是一个明显的“开关变量”,它拔向那一边,那么Oracle就会去找和它对应的参数文件来启动实例。其次SID也起到进程隔离的作用--即SID会在实例的一系列后台进程中得到体现,如ora_dbw0_paullin,ora_dbw0_boblin。通过SID来命名后台进程。

操作系统也必须通过SID来和Oracle实例打交道,操作系统并不知道什么,只知道ORACLE_SID,在Oracle内部由Oracle自己根据这个SID去识别不同的实例。所以ORACLE_SID更多的是“Oracle和外部操作系统沟通的一个窗口”。


【二】对INSTANCE_NAME的理解
相比于ORACLE_SID这样的“开关变量”,INSTANCE_NAME则是一个实实在在的参数。它是在init/pfile文件中配置的()。用于标识实例的名称,其缺省值就是ORACLE_SID。

INSTANCE_NAME就像一个人的名称一样,而SID则是这个人的身份证号码。通过SID我们找到对应的init/spfile文件,而init/spfile文件中又通过instance_name这个参数告诉我们对应的实例叫什么名字。这样就把ORACLE_SID、参数文件、INSTANCE_NAME联系起来了。

造成ORACLE_SID不同,但INSTANCE_NAME相同的原因通常是因为复制了原有的参数文件,但忘记了修改其中的INSTANCE_NAME参数的值。不过在10G之后INSTANCE_NAME这个参数以及从init/spfile中消失了,以免引起混乱。


【三】对DB_NAME的理解
我们已经知道了ORACLE_SID是一个“开关变量”,INSTANCE_NAME是用来描述实例的。那么DB_NAME则是描述实例挂载的数据库名称,通过这个DB_NAME我们可以知道对应的磁盘上的控制文件、日志文件、数据文件的位置。

DB_NAME在创建数据库时被指定,默认情况下和ORACLE_SID的名字一样。但和INSTANCE_NAME一样。DB_NAME一旦被确定下来就不能修改了,因为它会同时存储在init/spfie,控制文件,日志文件,数据文件。你只能修改init/spfile文件中DB_NAME参数的值,但是不能手工修改其它文件的值。所以一旦修改后引起几个文件的值不匹配那么数据库的启动就会失败。

A.一个实例可以MOUNT并打开任何数据库(通过init/spfile中配置DB_NAME参数),但是同一时间一个实例只能打开一个数据库。
B.一个数据库可以被一个或多个实例所MOUNT并打开(只能是在环境下,普通环境下一个数据库只能同时被一个实例MOUNT并打开)。

那么如何知道实例应该挂载到那个数据库并打开呢?就是靠init/spfile中的“control_files”参数来告诉Oracle去那里读取控制文件,而控制文件中又记录了数据文件的位置。所以最终形成一个完整的链条:

ORACLE_SID --> init/spfile文件 --> instance_name、db_name、control_files --> 实例名、数据库名、控制文件 --> 数据文件 --> 完成挂载并打开


【四】ORACLE_SID、INSTANCE_NAME、DB_NAME对应关系
我们已经知道ORACLE_SID是用来隔离同一个ORACLE_HOME下不同的实例的。但对于不同的ORACLE_HOME呢?能否有相同名称的SID呢?

实际上这就和文件系统的规则是一样的:在同一个目录下不允许有同名的文件存在,但不同的目录下可以有同名的文件。同样的在同一个ORACLE_HOME下不能有相同的SID存在,而不同的ORACLE_HOME下可以有重名的SID(即便是同一台机,只要ORACLE_HOME不同就可以)。

那么对于INSTANCE_NAME呢?默认情况下INSTANCE_NAME和ORACLE_SID是相同的,也可以是不同的;而且不同的实例可以具有相同的实例名。这听起来有点混乱是不?其实我们可以用一个简单的生活化例子来解析:

在一个班级Class_1里面,有两个学生,他们的名称都叫张三,但他们的学号肯定不同。在这里“张三”就是INSTANCE_NAME,而学号就是SID。所以INSTANCE_NAME重复没关系,只要SID不同就可以区分开来。

但是在另外一个班级Class_2里面,也有学号相同的学生,这时候就出现了我们说的SID相同的问题,那么如何区分呢?别忘了我们还有班级这个概念啊!对应于ORACLE就是ORACLE_HOME了。

至于INSTANCE_NAME和DB_NAME的对应关系,这个很好理解了,不同的实例可以挂载到不同的DB,也可以挂载到相同的DB嘛。可以把这理解为“多个进程同时对同一份磁盘文件的竞争性访问”。

A. 相同ORACLE_HOME下,INSTANCE_NAME可以相同,但ORACLE_SID必须唯一。通过ORACLE_SID来区分不同的实例
B. 不同ORACLE_HOME下,ORACLE_SID可以相同,通过ORACLE_HOME来区分不同的SID
C.不同INSTANCE_NAME可以对应不同的DB_NAME,也可以对应相同的DB_NAME。但是如果不是在RAC环境下,只能同时启动实例而不能同时挂载






【五】Oracle实例启动过程的相关参数文件

前面说到Oracle实例启动时,需要指定pfile/spfile参数,对应的就是init文件和spfile文件。那么当这两个文件同时存在时Oracle如何决定读取那个呢?

以Oracle 9i为例,由于默认采用了spfile来启动实例,所以查找的顺序是:

spfile.ora ---> spfile.ora ---> init.ora

即默认加载和SID对应的参数文件,如果找不到则采用默认的参数文件,再找不到就用旧的init文件,如果还是找不到则实例无法启动。下面我们来看看这些文件的内容(以Oracle 10g为例)

A.spfile.ora:

paullin.__db_cache_size=339738624
paullin.__java_pool_size
=4194304
paullin.__large_pool_size
=4194304
paullin.__shared_pool_size
=92274688
paullin.__streams_pool_size
=0
*.audit_file_dest
='C:\Develop\Oracle\product\10.2.0/admin/paullin/adump'
*.background_dump_dest
='C:\Develop\Oracle\product\10.2.0
/admin/paullin/bdump'
*.compatible
='10.2.0.1.0
'
*.control_files
='C:\Develop\Oracle\product\10.2.0\oradata\paullin\control01.ctl',

                     'C:\Develop\Oracle\product\
10.2.0\oradata\paullin\control02.ctl',
                     'C:\Develop\Oracle\product\
10.2.0\oradata\paullin\control03.ctl'
*.core_dump_dest
='C:\Develop\Oracle\product\10.2.0
/admin/paullin/cdump'
*.db_block_size
=8192

*.db_domain
=''
*.db_file_multiblock_read_count
=16

*.db_name
='paullin'
*.db_recovery_file_dest
='C:\Develop\Oracle\product\10.2.0
/flash_recovery_area'
*.db_recovery_file_dest_size
=2147483648

*.dispatchers
='(PROTOCOL=TCP) (SERVICE=paullinXDB)'
*.job_queue_processes
=10

*.open_cursors
=300
*.pga_aggregate_target
=148897792
*.processes
=150
*.remote_login_passwordfile
='EXCLUSIVE'
*.sga_target
=447741952

*.undo_management
='AUTO'
*.undo_tablespace
=
'UNDOTBS1'
*.user_dump_dest
='C:\Develop\Oracle\product\10.2.0/admin/paullin/udump'

B.init.ora

SPFILE='C:\Develop\Oracle\product\10.2.0\db_1/dbs/spfilepaullin.ora'

我们看到spfile.ora文件的内容就是我们创建数据库时在DBCA中填写的参数,而init.ora文件的内容则指向了该spfile,所以不论如何都是从spfile来启动实例了。


1个机器上可以同时运行2个相同sid的数据库实例, 但是这两个实例不能使用同一个ORACLE_HOME, 因为oracle使用sid和ORACLE_HOME的组合来标示一个运行中的实例. 

2 操作系统环境变量ORACLE_SID一般情况下和初始化参数instance_name保持一致, 如果不设置instance_name, 则他的值为ORACLE_SID, 但是也可以不一致, oracle向listener注册时使用的是instance_name. 

3  java的jdbc连接的时候,使用的是instance_name, 因为jdbc要通过listener 连接的数据库, 而listener只知道instance_name. 

4 listener会监听主机上的一个端口, 除非做特殊的配置, 否则他不会主动的监听任何实例. 实例启动后会向本地的1521或者locale_listener中配置的地址注册service, 而注册的依据就是instance_name, 当listener收到要求连接到特定service或instance_name的请求后, 就把这个请求转给注册这个service或instance_name的实例, 然后这个实例启动特定的进程为这个连接服务. 整个过程中不涉及ORACLE_SID环境变量. 

5 访问数据库通过service或者instance_name, 不需要db_name, db_name用来唯一标示数据库, 和访问无关. 


通常情况下, ORACLE_SID和instance_name是一致的, 所以这两者常常会被不加区分的使用.

阅读(764) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~