数据库可以由多个实例装载和打开,而实例可以在任何时间点装载和打开一个数据库。
· 实例是一组后台进程(Unix/Linux下)/线程(Windows下)和共享内存。
· 数据库是磁盘上存储的数据集合。
· 实例“一生”只能装载并打开一个数据库。
· 数据库可以由一个或多个实例(使用RAC)装载和打开。
专用服务器模式和共享服务器模式
Oracle服务器处理请求的两种最常见的方式,分别是专用服务器(dedicated server)连接和共享服务器(shared server)。
一个Oracle实例可以同时使用这两类连接(实际上,即使配置为使用共享服务器连接,Oracle数据库也总是支持专用服务器连接)。
专用服务器模式下,客户登录时,Oracle总会创建一个新的进程,这个服务器进程会在会话生存期中进行专门服务。对于每个会话,都会出现一个新的专用服务器,会话与专用服务器之间存在一对一的映射。按照定义,这个专用服务器不是实例的一部分。客户进程(也就是想要连接数据库的程序)会通过某种网络通道(如TCP/IP socket)与这个专用服务器直接通信,并由这个服务器进程接收和执行客户的SQL。
共享服务器(shared server),正式的说法是多线程服务器(Multi-Threaded Server)或MTS。如果采用这种方式,就不会对每条用户连接创建另外的线程或新的UNIX 进程。在共享服务器中,Oracle 使用一个“共享进程”池为大量用户提供服务。共享服务器实际上就是一种连接池机制。
共享服务器模式下,客户进程通过网络与一个调度器进程通信,客户连接向调度器发送一个请求。调度器首先将这个请求放在SGA中的请求队列中①。第一个可用的共享服务器从请求队列中取出这个请求②并处理。共享服务器的处理结束后,再把响应(返回码、数据等)放到响应队列中③,接下来调度器拿到这个响应④,传回给客户。
专用服务器模式下,因为存在一对一的映射,所以不必担心长时间运行的事务会阻塞其他事务。因此,在非OLTP环境中,也就是可能有长时间运行事务的情况下,应该只考虑使用这种模式。专用服务器是Oracle的推荐配置,它能很好地扩缩。
共享服务器只适用于OLTP 系统,这种系统的特点是事务短而且频繁。
使用共享服务器时,可能还会有人工死锁(artificial deadlock)。考虑下面这种情况,
有5个共享服务器,并建立了100 个用户会话,
假设其中一个用户会话更新了某一行,但没有提交,
这个时候可能又有另外5个用户会话力图锁住这一行,这5个会话会被阻塞,
现在,原来的用户会话(它持有这一行的锁)试图提交事务,相应地释放行上的锁,但是这时所有共享服务器都已经被那5个等待的会话所垄断,
这就出现了一个人工死锁的情况:锁的持有者永远也拿不到共享服务器来完成提交,除非某个等待的会话放弃其共享服务器。
如果应用中已经使用了连接池特性,就不要使用共享模式。
可以查看v$session的server列来得知当前连接是专用还是共享模式。
select server from v$session where sid = (select sid from v$mystat where rownum < 2);
server = 'DEDICATED'则是DEDICATED方式
server='SHARED'则是shared方式,并且正有shared_server_process为其服务
server='NONE'的话,则是shared方式,并且当前没有shared_server_process为其服务。
配置共享服务器模式需要设置如下2个参数:
1)dispatchers
alter system set dispatchers='(ADDRESS=(PROTOCOL=TCP))(DISPATCHERS=3)'
为TCP协议最初启动的dispatcher数为3。
2)shared_servers
alter system set shared_servers=5;
实例启动时创建的共享服务器数为5。把这个参数设置为0,之后新的连接揪都会使用专用服务器模式。
配置共享服务器模式可选参数有:
1) max_dispatchers
2) max_shared_servers
3) shared_server_sessions
相关的数据字典:
select * from v$shared_server;
select * from v$shared_server_monitor;
select * from v$dispatcher;
数据库常驻连接池DRCP
11g之后,引入数据库常驻连接池DRCP。有些应用API不提供高效连接池,DRCP为它们提供了一个。DRCP结合了专用服务器模式和共享服务器模式概念,它提供了服务器连接池,但是放入连接池的是专用服务器。
共享服务器模式下,一个会话可能使用多个共享服务器,但是DRCP下,从连接池中选出的专用服务器进程会在整个会话生命周期为客户进程所专用。
TNS 监听器
通过SQL*Plus连接Oracle,例如以下命令:
sqlplus scott/tiger@ORCL1
ORCL1是一个TNS服务名。TNS代表透明网络底层(Transparent Network Substrate),这是Oracle客户中处理远程连接的“基础”软件,有了它才有可能建立对等通信。
TNS连接串告诉Oracle软件如何与远程数据库连接。一般地,客户软件会读取一个tnsnames.ora文件。这是一个纯文本的配置文件,通常放在 [ORACLE_HOME]\network\admin 目录下。
在网络环境中,服务器上运行一个称为TNS 监听器的进程。这个监听器进程收到入站连接请求时,它会使用自己的配置文件检查这个请求,并真正建立连接。
如果建立一条专用服务器连接,监听器进程就会为我们创建一个专用服务器。如果是共享服务器连接请求,监听器进程知道实例中运行了哪些调度器。接收到连接请求后,监听器会从可用的调度器池中选择一个调度器进程。监听器会向客户返回连接信息,其中说明了客户如何与调度器进程连接;如果可能的话,还可以把连接“转发”给调度器进程。
下面是一个tnsnames.ora文件例子。注意:
1)端口号1521必须和listener使用的端口一致;
2)SERVICE_NAME必须和实例所使用的SERVICE NAME一致;
3)SERVER可以指定为DEDICATED或者SHARED。如果指定为SHARED,数据库SERVER必须配置成为共享服务器模式。
ORCL1 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = TONYPC)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl1.ora11gr2)
)
)
ORCL2 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = TONYPC)(PORT = 1521))
(CONNECT_DATA =
(SERVER = SHARED)
(SERVICE_NAME = orcl2.ora11gr2)
)
)
LISTENER
Oracle LISTENER监听的配置文件listener.ora位于$ORACLE_HOME/network/admin下面。例如:
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = TONYPC)(PORT = 1521))
)
)
可以使用lsnrctl命令管理listener。在命令行键入lsnrctl,在LSNRCTL>提示符下键入help来显示这些命令。
注意可以在listener.ora中定义多个listener,使用lsnrctl start/status/stop <listener name>来管理指定的listener。
*在listener.ora中有时可以看到CLRExtProc服务,这是.net扩展使用的SID.
By default, Oracle Database Extensions for .NET uses CLRExtProc as the SID, but this can be changed using the Database Configuration Assistant (DBCA).
SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = CLRExtProc)
(ORACLE_HOME = E:\app\oracle\product\11.2.0\dbhome_1)
(PROGRAM = extproc)
(ENVS = "EXTPROC_DLLS=ONLY:E:\app\oracle\product\11.2.0\dbhome_1\bin\oraclr11.dll")
)
)
*lsnrctl status或者lsnrctl services命令的输出中有时可以看到*XDB服务,这是oracle XML DB组件。查看dispatchers参数,会发现有'(PROTOCOL=TCP) (SERVICE=XDB)'的设置。
禁用XDB只需要从dispatchers参数中去掉以上部分。
修改监听端口
如果不是默认的监听端口1521,需要通过local_listener参数来指定监听端口。
当前有2个数据库实例,ORCL1和ORCL2,ORCL2启用了share server模式。使用默认的listener,端口1521。
现在把端口修改为1528的listener,给ORCL2使用。
1) 修改listener.ora文件,端口改成1528。
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = TONYPC)(PORT = 1528))
)
)
2) 修改ORCL1和ORCL2的local_listener参数,
H:\>sqlplus /@orcl1 as sysdba
sys@ORCL1> alter system set local_listener = '(ADDRESS = (PROTOCOL = TCP)(PORT = 1528))';
System altered.
sys@ORCL1> exit
H:\>sqlplus /@orcl2 as sysdba
sys@ORCL2> alter system set local_listener = '(ADDRESS = (PROTOCOL = TCP)(PORT = 1528))';
System altered.
sys@ORCL2> exit
3)修改tnsnames.ora文件,端口修改成1528
ORCL2 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = TONYPC)(PORT = 1528))
(CONNECT_DATA =
(SERVER = SHARED)
(SERVICE_NAME = orcl2.ora11gr2)
)
)
ORCL1 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = TONYPC)(PORT = 1528))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl1.ora11gr2)
)
)
4)重启listener
H:\>lsnrctl
LSNRCTL> stop
LSNRCTL> start
可以用netstat -na | find "1528"命令来确认是否端口已经改变。
可以用tnsping ORCL1,tnsping ORCL2命令来验证可以连接数据库。
5)连接数据库
H:\>sqlplus /@orcl1 as sysdba
H:\>sqlplus /@orcl2 as sysdba
6)查看listener的状态
LSNRCTL> status
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
STATUS of the LISTENER
------------------------
Alias LISTENER
Version TNSLSNR for 32-bit Windows: Version 11.2.0.1.0 - Production
Start Date 01-APR-2012 13:08:35
Uptime 0 days 0 hr. 22 min. 47 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Listener Parameter File E:\app\oracle\product\11.2.0\dbhome_1\network\admin\listener.ora
Listener Log File e:\app\oracle\diag\tnslsnr\TONYPC\listener\alert\log.xml
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1521ipc)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=TONYPC)(PORT=1528)))
Services Summary...
Service "CLRExtProc" has 1 instance(s).
Instance "CLRExtProc", status UNKNOWN, has 1 handler(s) for this service...
Service "orcl1.ora11gr2" has 1 instance(s).
Instance "orcl1", status READY, has 1 handler(s) for this service...
Service "orcl2.ora11gr2" has 1 instance(s).
Instance "orcl2", status READY, has 4 handler(s) for this service...
The command completed successfully
LSNRCTL> services
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))
Services Summary...
Service "CLRExtProc" has 1 instance(s).
Instance "CLRExtProc", status UNKNOWN, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0
LOCAL SERVER
Service "orcl1.ora11gr2" has 1 instance(s).
Instance "orcl1", status READY, has 1 handler(s) for this service...
Handler(s):
"DEDICATED" established:1 refused:0 state:ready
LOCAL SERVER
Service "orcl2.ora11gr2" has 1 instance(s).
Instance "orcl2", status READY, has 4 handler(s) for this service...
Handler(s):
"DEDICATED" established:0 refused:0 state:ready
LOCAL SERVER
"D002" established:0 refused:0 current:0 max:1022 state:ready
DISPATCHER <machine: TONYPC, pid: 12888>
(ADDRESS=(PROTOCOL=tcp)(HOST=TONYPC)(PORT=3086))
"D001" established:0 refused:0 current:0 max:1022 state:ready
DISPATCHER <machine: TONYPC, pid: 14040>
(ADDRESS=(PROTOCOL=tcp)(HOST=TONYPC)(PORT=3085))
"D000" established:1 refused:0 current:1 max:1022 state:ready
DISPATCHER <machine: TONYPC, pid: 10464>
(ADDRESS=(PROTOCOL=tcp)(HOST=TONYPC)(PORT=3084))
The command completed successfully
LSNRCTL>