ORACLE 体系结构
(Architecture of ORACLE)
?
第一部分:ORACLE8i体系结构
在本章里你可以了解以下内容
1、 理解ORACLE 实例的组成
2、 理解ORACLE 数据库的组成
3、 理解ORACLE内存结构的组成
4、 理解后台进程的作用与分工
5、 理解数据库的物理文件与对应的逻辑结构
6、 理解ORACLE的整体构架
ORACLE是一个可移植的数据库——它在相关的每一个平台上都可以使用,即所谓的跨平台特性。在不同的操作系统上也略有差别,如在UNIX/LINUX上,ORACLE是多个进程实现的,每一个主要函数都是一个进程;而在Windows上,则是一个单一进程,但是在该进程中包含多个线程。但是从整体构架上来看,ORACLE在不同的平台上是一样的,如内存结构、后台进程、数据的存储。
一个运行着的ORACLE数据库就可以看成是一个ORACLE SERVER,该SERVER由数据库(Database)和实例(Instance)组成,在一般的情况下一个ORACLE SERVER包含一个实例和一个与之对应的数据库,但是在特殊情况下,如8i的OPS,9i的RAC,一个SERVER中一个数据库可以对应多个实例。
一系列物理文件(数据文件,控制文件,联机日志等)的集合或与之对应的逻辑结构(表空间,段等)被称为数据库,简单的说,就是一系列与磁盘有关系的物理文件的组成。ORACLE内存结构和后台进程被成为数据库的实例,一个实例最多只能安装(Mount)和打开(Open)在一个数据库上,负责数据库的相应操作并与用户交互。
实例与数据库的关系如下图所示:
图一 ORACLE SERVER
Oracle内存结构主要可以分共享内存区与非共享内存区,共享内存区主要包含系统全局区SGA(System Global Area),非共享内存区主要由程序全局区PGA(Program Global Area)组成,可以用如下图形表示。
图二 ORACLE MEMOERY STRUCTRUE
System Global Area 是一块巨大的共享内存区域,他被看做是Oracle 数据库的一个大缓冲池,这里的数据可以被ORACLE的各个进程共用。其大小可以通过如下语句查看:
SQL> select * from v$sga;
NAME VALUE
-------------------- ---------
Fixed Size 39816
Variable Size 259812784
Database Buffers 1.049E+09
Redo Buffers 327680
更详细的信息可以参考V$sgastat、V$buffer_pool
主要包括以下几个部分:
共享池是SGA中最关键的内存片段,特别是在性能和可伸缩性上。一个太小的共享池会扼杀性能,使系统停止,太大的共享池也会有同样的效果,将会消耗大量的CPU来管理这个共享池。不正确的使用共享池只会带来灾难。共享池主要又可以分为以下两个部分:
1、SQL语句缓冲(Library Cache)
当一个用户提交一个SQL语句,Oracle会将这句SQL进行分析(parse),这个过程类似于编译,会耗费相对较多的时间。在分析完这个SQL,Oracle会把他的分析结果给保存在Shared pool的Library Cache中,当数据库第二次执行该SQL时,Oracle自动跳过这个分析过程,从而减少了系统运行的时间。这也是为什么第一次运行的SQL 比第二次运行的SQL要慢一点的原因。
下面举例说明parse的时间
SQL>Startup
SQL> select count(*) from usertable;
COUNT(*)
----------
243
Elapsed: 00:00:00.08
这是在Share_pool 和Data buffer 都没有数据缓冲区的情况下所用的时间
SQL> alter system flush SHARED_POOL;
System altered.
清空Share_pool,保留Data buffer
SQL> select count(*) from usertable;
COUNT(*)
-----------------
243
Elapsed: 00:00:00.02
SQL> select count(*) from usertable;
COUNT(*)
----------------
243
Elapsed: 00:00:00.00
从两句SQL 的时间差上可以看出该SQL 的Parse 时间约为00:00:00.02
对于保存在共享池中的SQL语句,可以从V$Sqltext、v$Sqlarea中查询到,对于编程者来说,要尽量提高语句的重用率,减少语句的分析时间。一个设计的差的应用程序可以毁掉整个数据库的Share pool,提高SQL语句的重用率必须先养成良好的变成习惯,尽量使用Bind变量。
2、数据字典缓冲区(Data Dictionary Cache)
显而易见,数据字典缓冲区是ORACLE特地为数据字典准备的一块缓冲池,供ORACLE内部使用,没有什么可以说的。
这些缓冲是对应所有数据文件中的一些被使用到的数据块。让他们能够在内存中进行操作。在这个级别里没有系统文件,,户数据文件,临时数据文件,回滚段文件之分。也就是任何文件的数据块都有可能被缓冲。数据库的任何修改都在该缓冲里完成,并由DBWR进程将修改后的数据写入磁盘。
这个缓冲区的块基本上在两个不同的列表中管理。一个是块的“脏”表(Dirty List),需要用数据库块的书写器(DBWR)---数据库写入进程来写入,另外一个是不脏的块的列表(LRU List),一般的情况下,是使用最近最少使用(Least Recently Used,LRU)算法来管理。
块缓冲区高速缓存又可以细分为以下三个部分(Default pool,Keep pool,Recycle pool)。如果不是人为设置初始化参数(Init.ora),ORACLE将默认为Default pool。
由于操作系统寻址能力的限制,不通过特殊设置,在32位的系统上,块缓冲区高速缓存最大可以达到 1.7G ,在64位系统上,块缓冲区高速缓存最大可以达到 10G 。
重做日志文件的缓冲区,对数据库的任何修改都按顺序被记录在该缓冲,然后由LGWR进程将它写入磁盘。这些修改信息可能是DML语句,如(Insert,Update,Delete),或DDL语句,如(Create,Alter,Drop等)。
重做日志缓冲区的存在是因为内存到内存的操作比较内存到硬盘的速度快很多,所以重作日志缓冲区可以加快数据库的操作速度,但是考虑的数据库的一致性与可恢复性,数据在重做日志缓冲区中的滞留时间不会很长。所以重作日志缓冲区一般都很小,大于 3M 之后的重作日志缓冲区已经没有太大的实际意义。
Java 的程序区,Oracle 8I 以后,Oracle 在内核中加入了对Java的支持。该程序缓冲区就是为Java 程序保留的。为Java提供语法分析区。如果不用Java程序没有必要改变该缓冲区的默认大小。他的大小在init.ora文件的JAVA_POOL_SIZE来设置,默认 10M 。
大池的得名不是因为大,而是因为它用来分配大块的内存,处理比共享池更大的内存,在8.0开始引入。
下面对象使用大池:
1、? MTS——在SGA的Large Pool中分配UGA
2、? 语句的并行查询(Parallel Executeion of Statements)——允许进程间消息缓冲区的分配,用来协调并行查询服务器
3、? 备份(Backup)——用于RMAN磁盘I/O缓存
Program Global Area(PGA)是用来保存与用户进程相关的内存段,PGA总是由进程或线程在本地分配,其它进程与线程无法访问。--------所以非共享J
User Global Area(UGA)实际上是会话的状态,它是会话必须始终能够得到的内存。对于专用服务器进程,UGA在PGA中分配。对于多线程进程,UGA在Large pool中分配。
PGA/UGA一般保存了用户的变量、权限、堆栈、排序(Sort)空间等信息。影响PGA/UGA最大的也就是Sort信息,由初始化参数sort_area_size决定,由于Sort信息分配在UGA中,所以在共享服务器中能更好的利用内存。
后台进程是Oracle的程序,用来管理数据库的读写,恢复和监视等工作。Server Process主要是通过他和user process进行联系和沟通,并由他和user process进行数据的交换。在Unix机器上,Oracle后台进程相对于操作系统进程,也就是说,一个Oracle后台进程将启动一个操作系统进程;在Windows机器上,Oracle后台进程相对于操作系统线程,打开任务管理器,我们只能看到一个ORACLE.EXE的进程,但是通过另外的工具,就可以看到包含在这里进程中的线程。后台进程与其它结构的关系如图所示:
图三ORACLE BACKGROUP PROCESS
在Unix上可以通过如下方法查看后台进程:
ps –ef | grep ora_
# ps -ef | grep ora_ | grep XCLUAT
oracle 29431 1 0 Sep 02 ? 2:02 ora_dbwr_SID
oracle 29444 1 0 Sep 02 ? 0:03 ora_ckpt_SID
oracle 29448 1 0 Sep 02 ? 2:42 ora_smon_SID
oracle 29442 1 0 Sep 02 ? 3:25 ora_lgwr_SID
oracle 29427 1 0 Sep 02 ? 0:01 ora_pmon_SID
Oracle系统有5 个基本进程他们是
DBWR(数据文件写入进程)
LGWR(日志文件写入进程)
SMON(系统监护进程)
PMON(用户进程监护进程)
CKPT(检查点进程,同步数据文件, 日志文件,控制文件)
将修改过的数据缓冲区的数据写入对应数据文件
维护系统内的空缓冲区
这里指出几个容易错误的概念:
·当一个更新提交后,DBWR把数据写到磁盘并返回给用户提交完成。
·DBWR会触发CKPT 后台进程
·DBWR不会触发LGWR 进程
上面的概念都是错误的。
DBWR是一个很底层的工作进程,他批量的把缓冲区的数据写入磁盘。和任何前台用户的进程几乎没有什么关系,也不受他们的控制。至于DBWR会不会触发LGWR和CKPT进程,我们将在下面几节里讨论。//也就是说,DBWR进程不会在一个更新提交后把数据写到磁盘,他会批量的自己决定什么时候把缓冲区的数据写入磁盘J
DBWR工作的主要条件如下
·DBWR 超时
·系统中没有多的空缓冲区用来存放数据
·CKPT 进程触发DBWR 等
将重做日志缓冲区的数据写入重做日志文件,LGWR是一个必须和前台用户进程通信的进程。当数据被修改的时候,系统会产生一个重做日志并记录在重做日志缓冲区内。这个重做日志可以类似的认为是以下的一个结构:
SCN=000000001000
数据块ID
对象ID=0801
数据行=02
修改后的数据=0011
提交的时候,LGWR必须将被修改的数据的重做日志缓冲区内数据写入日志数据文件,然后再通知前台进程提交成功,并由前台进程通知用户。从这点可以看出LGWR承担了维护系统数据完整性的任务。
LGWR 工作的主要条件如下
·用户提交
·有1/3 重做日志缓冲区未被写入磁盘
·有大于 1M 重做日志缓冲区未被写入磁盘
·超时
·DBWR需要写入的数据的SCN号大于LGWR 记录的SCN号,DBWR 触发LGWR写入
工作主要包含
·清除临时空间
·在系统启动时,完成系统实例恢复
·聚结空闲空间
·从不可用的文件中恢复事务的活动
·OPS中失败节点的实例恢复
·清除OBJ$表
·缩减回滚段
·使回滚段脱机
主要用于清除失效的用户进程,释放用户进程所用的资源。如PMON将回滚未提交的工作,释放锁,释放分配给失败进程的SGA资源。
同步数据文件,日志文件和控制文件,由于DBWR/LGWR的工作原理,造成了数据文件,日志文件,控制文件的不一至,这就需要CKPT进程来同步。CKPT会更新数据文件/控制文件的头信息。
CKPT工作的主要条件如下
·在日志切换的时候
·数据库用immediate ,transaction , normal 选项shutdown 数据库的时候
·根据初始话文件LOG_CHECKPOINT_INTERVAL、LOG_CHECKPOINT_TIMEOUT、FAST_START_IO_TARGET 的设置的数值来确定
·用户触发
以下进程的启动需要手工配置
当数据库以归档方式运行的时候,Oracle会启动ARCH进程,当重做日志文件被写满时,日志文件进行切换,旧的重做日志文件就被ARCH进程复制到一个/多个特定的目录/远程机器。这些被复制的重做日志文件被叫做归档日志文件。
负责解决分布事物中的故障。Oracle可以连接远程的多个数据库,当由于网络问题,有些事物处于悬而未决的状态。RECO进程试图建立与远程服务器的通信,当故障消除后,RECO进程自动解决所有悬而未决的会话。
服务进程的分类
·专用服务进程(Dedicated Server Process)
一个服务进程对应一个用户进程
·共享服务进程(MultiTreaded Server Process)
一个服务进程对应多个用户进程,轮流为用户进程服务。
在客户端,负责将用户的SQL 语句传递给服务进程,并从服务器段拿回查询数据。
系统改变号,一个由系统内部维护的序列号。当系统需要更新的时候自动增加,他是系统中维持数据的一致性和顺序恢复的重要标志。
运行以下语句可以得到系统SCN号
SQL> select max(ktuxescnw * power(2, 32) + ktuxescnb) scn from x$ktuxe;
?? SCN
----------
? 3 1014
SCN有如下特点:
a. 查询语句不会使SCN增加,就算是同时发生的更新,数据库内部对应的SCN也是不同的。这样一来就保证了数据恢复时候的顺序。
b. 维持数据的一致性,当一个查询执行的时候,他会先从系统中得到一个当前的SCN号,在他查找数据的同时,他会检查每个数据行和他对应的SCN号,只有那些不比他的SCN号大的行才能从对应用户数据文件的缓冲区内取出,而那些大于他SCN号的行,就应该从回滚段数据文件的缓冲中取出。
实例分析:
一个查询返回以下5 行
ID Name
-------------------------------------
1 ShangHai
2 Beijing
3 Gugangzhou
4 ShenZhen
5 HanZhou
用户A从12:00开始运行,到12:05结束在12:01用户B执行了一条Update语句,更新了ID是2的那条记录把Beijing该成了Tianjing.并提交,这时候用户A 的那个查询是不会出现Tianjing的记录。12:00查询时候的SCN是N然后用户B的更新使得系统的SCN变成N+1当用户A查询到ID=2的记录的时候发现他的SCN已经大于查询开始时候的SCN,他就会在回滚段数据缓冲中找到SCN=N的那条记录,并把它返回。
参数文件init.ora记录了控制文件的位置,控制文件是一个非常小的二进制文件,最大可以增长到64MB,控制文件包括如下主要信息
·数据库的名字,检查点信息,数据库创建的时间戳
·所有的数据文件,联机日志文件,归档日志文件信息
·备份信息等
有了这些信息,Oracle就知道那些文件是数据文件,现在的重做日志文件是哪些,这些都是系统启动和运行的基本条件,所以他是Oracle运行的根本。如果没有控制文件系统是不可能启动的。控制文件是非常重要的,一般采用多个镜相复制来保护控制文件,或采用RAID来保护控制文件。控制文件的丢失,将使数据库的恢复变的很复杂。
控制文件信息可以从V$Controlfile中查询获得
数据文件的详细信息记载在控制文件中
可以通过如下方式查看数据文件
SQL> select name from v$datafile;
NAME
---------------------------------------------
/u05/dbf/PROD/system_01.dbf
/u06/dbf/PROD/temp_01.dbf
/u04/dbf/PROD/users_01.dbf
/u09/dbf/PROD/rbs_01.dbf
/u06/dbf/PROD/applsys_indx_01.dbf
/u05/dbf/PROD/applsys_data_01.dbf
数据文件是ORACLE中最重要的物理文件,直接记录了用户数据。按照使用上的不同,可以把数据文件分成如下几类:
·系统数据文件
·回滚数据文件
·临时数据文件
·用户数据文件
以上各类文件分别属于不同性质的表空间,在以下的逻辑结构中,将进一步说明该类型文件的作用。
用户对数据库进行的任何操作都会记录在重做日志文件。在了解重做日志之前必须了解重做日志的两个概念,重做日志组和重做日志组成员(Member),一个数据库中至少要有两个日志组文件,一组写完后再写另一组,即轮流写。每个日志组中至少有一个日志成员,一个日志组中的多个日志成员是镜相关系,有利于日志文件的保护,因为日志文件的损坏,特别是当前联机日志的损坏,对数据库的影响是巨大的。
联机日志组的交换过程叫做切换,需要特别注意的是,日志切换在一个优化效果不好的数据库中会引起临时的“挂起”。挂起大致有两种情况:
·在归档情况下,需要归档的日志来不及归档,而联机日志又需要被重新利用
·检查点事件还没有完成(日志切换引起检查点),而联机日志需要被重新利用
解决这种问题的常用手段是:
i.增加日志组
ii.增大日志文件成员大小
一个包含三个日志组,每个日志组两个成员的联机日志组成与运行大致如图所示:
图四 REDO LOG
通过v$log可以查看日志组,v$logfile可以查看具体的成员文件。
Oracle可以运行在两种模式之中,归档模式和不归档模式。如果不用归档模式,当然,你就不会有归档日志,但是,你的系统将不会是一个实用系统,特别是不能用于生产系统,因为你可能会丢失数据。但是在归档模式中,为了保存用户的所有修改,在重做日志文件切换后和被覆盖之间系统将他们另外保存成一组连续的文件系列,该文件系列就是归档日志文件。
有人或许会说,归档日志文件占领我大量的硬盘空间,其实,具体想一想,你是愿意浪费一点磁盘空间来保护你的数据,还是愿意丢失你的数据呢?显而义见,我们需要保证我们的数据的安全性。其实,归档并不是一直占领你的磁盘空间,你可以把她备份到磁带上,或则删除上一次完整备份前的所有日志文件。
通过v$archived_log和v$log_history可以查看归档日志文件的信息。
initSID.ora或init.ora文件,因为版本的不一样,其位置也可能会不一样。在8i中,通常位于$ORACLE_HOME/admin/ /Pfile 下。在9i以下参数文件是一个纯文本文件,可以用文本编辑器打开修改,从9i开始,多了一个叫spfile的参数文件,以二进制方式保存。
初始化文件记载了许多数据库的启动参数,如内存,控制文件,进程数等,在数据库启动的时候加载(Nomount时加载),初始化文件记录了很多重要参数,对数据库的性能影响很大,如果没有它,数据库将无法启动。在9i以前,对参数文件的修改,必须重新启动数据库才能使参数生效,从9i开始,可以用命令来修改spfile文件的内容了。
参数文件中的参数不是一直一成不变的,随着版本的不同而不同。大多数参数,如Db_block_size的寿命就很长,其它很多参数随着版本的改变就被废弃了。除了文档记录的参数外,ORACLE还支持很多内部参数,当然,这些参数是不建议被使用的。
通过v$parameter视图可以查询当前的参数设置。
i . 密码文件
用于Oracle 的具有sysdba权限用户的认证,在9i以前主要指Internal用户,从9i开始已经取消了这个用户。密码文件的密码可以通过ORAPWD命令来修改。
ii. 日志文件
·报警日志文件(alert.log或alrt .ora )
记录数据库启动,关闭和一些重要的出错信息。数据库管理员应该经常检查这个文件,并对出现的问题作出即使的反应。你可以通过以下SQL 找到他的路径select value from v$parameter where name ='background_dump_dest',或通过参数文件获得其路径。
·后台跟踪文件
路径与报警文件路径一致,记载了系统后台进程出错时写入的信息。
·用户跟踪文件
记载了用户进程出错时写入的信息,一般不可能读懂,可以通过ORACLE的TKPROF工具转化为可以读懂的格式。用户跟踪文件的路径,你可以通过以下SQL找到他的路径select value from v$parameter where name ='user_dump_dest',或通过参数文件获得其路径。
可以通过设置用户跟踪或dump命令来产生用户跟踪文件,一般在调试、优化、系统分析中有很大的作用。
ORACLE逻辑结构由一系列有相互关系的逻辑对象组成。如图:
图五LOGICAL STRUCTURE
表空间是数据库中的基本逻辑结构,一系列数据文件的集合。一个表空间可以包含多个数据文件,但是一个数据文件只能属于一个表空间。
在8i以前,表空间的管理类型只有一种,被称为字典管理表空间(DMT),即在数据字典中管理表空间中的空间的分配。在8i以后的版本,为了减少在字典上的开销,引入了本地管理的表空间(LMT),在该类型的表空间中,在每个数据文件中存储的位图来管理空间的分配,不再要求使用数据字典。本地管理的表空间有速度快,无碎片等众多优点,建议用户表空间都实现本地管理。
通过v$tablespace可以查询表空间,DBA_TABLESPACE可以查询详细表空间信息。
段是对象在数据库中占用的空间,虽然段和数据库对象是一一对应的,但段是从数据库存储的角度来看的。一个段只能属于一个表空间,当然一个表空间可以有多个段。
表空间和数据文件是物理存储上的一对多的关系,表空间和段是逻辑存储上的一对多的关系,段不直接和数据文件发生关系。一个段可以属于多个数据文件,关于段可以指定扩展到哪个数据文件上面。
段基本可以分为以下四种
·数据段(Data Segment)
·索引段(Index Segment)
·回滚段(Rollback Segment)
·临时段(Temporary Segment)
通过DBA/ALL/USER_SEGMENTS可以查询详细的段信息。
关于Extent的翻译有多种解释,有的译作扩展,有的译作盘区,我这里通常译为区间。在一个段中可以存在多个区间,区间是为数据一次性预留的一个较大的存储空间,直到那个区间被用满,数据库会继续申请一个新的预留存储空间,即新的区间,一直到段的最大区间数(Max Extent)或没有可用的磁盘空间可以申请。
在ORACLE8i以上版本,理论上一个段可以无穷个区间,但是多个区间对ORACLE却是有性能影响的,ORACLE建议把数据分布在尽量少的区间上,以减少ORACLE的管理与磁头的移动,但是在某些特殊情况下,需要把一个段分布在多个数据文件或多个设备上,适当的加多区间数也是有很大好处的。
通过DBA/ALL/USER_EXTENTS可以查询详细的区间信息。
ORACLE最基本的存储单位,在建立数据库的时候指定,虽然在初始化文件中可见,但是不能修改。为了保证存取的速度,它是OS数据块的整数倍。ORACLE的操作都是以块为基本单位,一个区间可以包含多个块,如果区间大小不是块大小的整数倍,ORACLE实际也扩展到块的整数倍。
块的内部结构与数据的存取方法都是比较复杂的,以表段的块为例,从简单的结构上划分,可以把块的内部划分成如下几个部分:公用头,表目录,行目录,可存取空间等。
以下是一个表块的大致结构图:
图六 TABLE BLOCK
块头(BLOCK HEADER)包含着关于块类型(表块、索引块等等)的信息、关于块上活动和过时事务信息、磁盘上筷的地址的信息。表目录(Table directory),如果给出的话,包含着此块中存储各行的表的信息(多个表的数据可能保存在同一个块中)。行目录(Row directory)包含在块中发现的描述行的信息。以上3部分为块的开销(Block Overhead),其余部分为可用存储空间,可以用如下查询获得可用空间大小。
Select kvisval,kvistag,kvisdsc from sys.x$kvis;
一般的8K(8192)的块可用空间为8168
PCTFREE与PCTUSED是表的两个存取参数,其实是作用在表中的块上面的,PCTFREE与PCTUSED表示两个百分比,默认分别是10与40。PCTFREE表示保留该百分比的可用空间用于以后的行更新,避免行迁移。如果行数据达到PCTFREE保留的空间,该块从FREE LIST上撤消下来,不再接收数据。PCTUSED表示当行的空闲空间降低(如删除数据)到该参数指定的百分比的时候,该块重新进入FREE LIST,开始接收新的数据。PCTFREE与PCTUSED的配置与系统的优化有一定的关系,所以要慎重,PCTFREE+PCTUSED不要大于等于100,否则将导致块不断的在FREELIST移上移下,严重影响性能。
该表空间包含的数据文件称为系统数据文件。
该表空间存放系统表和数据字典,一般不放用户的数据,但是用户脚本,如过程,函数,包等却是保存在数据字典中的。
数据字典是一些系统表或视图,他存放系统的信息,他包括数据库版本,数据文件信息,表与索引等段信息,系统的运行状态等各种和系统有关的信息和用户脚本信息。数据库管理员可以通过对数据字典的查询,就可以了解到Oracle的运行状态。
查看数据数据字典的SQL
select * from dict
查看内部系统表的SQL
select * from v$fixed_view_definition
DBA对系统的系统表中的数据字典必须有一个很深刻的了解,他们必须准备一些基础的SQL语句,通过这些SQL可以立即了解系统的状况和数据库的状态,这些基本的SQL包括
·系统的剩余空间
·系统的SGA
·状态系统的等待
·用户的权限
·当前的用户锁
·缓冲区的使用状况等
在成为DBA 的道路上我们不建议你过分的依赖于OEM/Quest 等优秀的数据库管理工具,因为他们不利于你对数据数据字典的理解,SQL语句可以完成几乎全部的数据库管理工作。
大量的读少量的写是该表空间的一个显著的特点。
该表空间包含的数据文件称为临时数据文件
主要存放用户的排序等临时数据,因为没有办法在一个永久表空间上开辟临时段,所以就必须有一个临时表空间,主要用于不能在内存上进行的排序操作。我们必须为用户指定一个临时表空间。
临时段占有的空间会在下次系统启动的时候全部被释放。
如果数据库进行对数据的修改,那么就必须使用回滚段,回滚段是用来临时存放修改前的数据(UNDO)。回滚段通常都放在一个单独的表空间上(回滚表空间),避免表空间碎片化,这个表空间包含的数据文件就是回滚数据文件。
当数据库进行更新插入删除等操作的时候,新的数据被更新到原来的数据文件,而旧的数据(Before Image)就被放到回滚段中,如果数据需要回滚,那么可以从回滚段将数据再复制到数据文件中。来完成数据的回滚。在系统恢复的时候, 回滚段可以用来回滚没有被commit 的数据,解决系统的一直性读。
回滚段在一般情况下都是大量的写,少量读,因此建议把回滚段单独出来放在一个单独的设备(如单独的磁盘或RAID),以减少磁盘的IO争用。
·一个回滚表空间可以被划分成多个回滚段.
·一个回滚段可以保存多个会话的数据.
·回滚段是一个圆形的数据模型
假设回滚段由4 个区间组成,他们的使用顺序就是区间1à区间2à区间3à区间4à区间1。也就是说,区间是可以循环使用的,当区间4到区间1的时候,区间1里面的会话还没有结束, 区间4用完后就不能再用区间1,这时系统必须分配区间5,来继续为其他会话服务服务。这也就是为什么回滚段在大事务的情况下会不断“涨大”的原因,回滚段的扩充是影响性能的,要尽量避免。
这是一个回滚段从4个区间简单的扩充到5个区间的例子:
图七 ROLLBACK SEGMENT
我们分析一个Update 语句的完成
1、用户提交一个Update 语句
2、Server Process 检查内存缓冲.
如果没有该数据块的缓冲,则从磁盘读入
i. 如果没有内存的有效空间,DBWR被启动将未写入磁盘的脏缓冲写入磁盘
ii. 如果有有效空间,则读入
3、在缓冲内更新数据
i. 申请一个回滚段入口,将旧数据写如回滚段
ii. 加锁并更新数据
iii. 并在同时将修改记录在Redo log buffer中
4、用户提交一个Commit 语句
i. SCN增加
ii. 将Redo log buffer 写入Redo log file
iii. 返回用户Commit 完成
其包含的数据文件称为用户数据文件
一般是由用户建立,来存取用户数据的表空间,一般有两类常见的用户型数据,数据和索引,一般来说,如果条件许可的话,可以考虑放在不同的磁盘上。
1、实例和SID的关系是什么?
经常有人问SID 是什么?在Oracle 系统中SID 是一个经常出现的变量,如环境变量ORACLE_SID, 初始化文件initSID.ora,那究竟什么是SID 呢?其实SID 就是Oracle 实例的标识,不同的SID 对应不同的内存缓冲(SGA)和不同的后台进程。这样一来我们就可以得当在一台物理的服务器上可以有多个SID 的数据库实例。
2、Oracle数据库和实例的关系是什么?
数据库是由物理文件和存取数据文件的实例组成,当存取数据文件的实例是一个的时候,数据库被称做单节点数据库。这是我们看到的最多的数据库形式。当然还有一种多节点数据库,就是一个以上的实例共同访问一个数据库(或者说共同访问一组数据文件), 更好的提供稳定性和并行处理能力。这在8i中被称为OPS(Oracle Parallel Server ),在Oracle9i 中被称为RAC(real application cluster)。在这种数据库中。两个/多个实例分别在不同服务器上,所有Oracle 数据文件在共享的磁盘阵列上,多个服务器上的实例可以同时工作,他们通过一个内部的网络进行通信。如果一台服务器不能提供服务的话,另一台会接管它的工作,特别是在关键的业务有很大的潜力。
3、在运行的数据库中数据文件中是不是可能存在没有被提交的数据?
这是可能存在的,因为用户数据文件的数据是由DBWR写入的,DBWR是一个很底层的后台进程,不负责与用户交互。用户的交互是由LGWR完成的。
4、在问题3中,如果存在没有写入的数据,那么机器突然断电,数据完整性会不会损坏?
不会的,因为数据库的完整性是LGWR来保证的,而且ORACLE保证了DBWR写入数据文件的任何修改已经被记录在重做日志文件中。当系统再次启动的时候,通过读取重做日志文件就可以知道那些数据没有被提交。这时候ORACLE 会自动回滚那些数据。所以说联机日志的损坏,特别是当前联机日志的损坏,对数据库的影响是巨大的,可能会导致数据库的不完整。
5、数据文件损坏会丢失数据吗?
可以这么说,如果你有备份和归档,就不会。因为所有对数据修改的记录都在重做日志中有记录,所以不会丢失数据,你只要恢复以前的备份再用归档日志文件恢复和当前的在线重做日志就可以恢复所有数据。
6、在线重做日志损坏会丢失数据吗?
以上说了,在线日志对数据库的损坏是极大的,所以不仅可能丢失数据,还可能引起数据库的不同步。在重做日志中的所有commit的记录都会丢失,这也是Oracle 为什么要对在线重做日志文件做镜像的原因。任何的数据丢失都是不允许的。
7、我在事务能不能指定不写回滚段?
不可以的,写回滚段是ORACLE保证一致性读和事务一致性的根本。回滚段是高写入段,建议把它放到单独的设备上来。
对于DDL语句,如DROP,TRUNCATE却可以不写回滚段(没有UNDO信息),所以对于整个表的删除,如果数据量比较大,建议用Truncate Table的方法。也就是说,DROP一个表后不可能通过rollback恢复!!J
不写联机日志也是不可能的,但可以在某些特定操作中,可以写很少的联机日志,如以NOLOGGING的方式通过Create table tablename as select创建表,或以Append的方式Insert数据到表,或直接载入等操作。
这里,我们了解了实例和数据库的关系,一个数据库可以有多个实例,但是一个实例却不可能对应多个数据库,在一般的情况下,我们都是用的单节点数据库,即一个实例仅仅对应一个数据库。
我们了解了ORACLE实例的组成,包括内存和后台进程,进一步解释了SGA的组成与SGA的作用,并分析了语句重用的好处。在后台进程中,重要的阐述了DBWR与LGWR,其中DBWR是一个底层的由ORACLE控制的后台进程,而LGWR负责与用户交互.
在ORACLE数据库中,我们重要阐述了数据库的物理与逻辑结构,在物理结构中,需要注意四类以下文件:控制文件,联机日志,数据文件与参数文件。在逻辑结构中,需要清楚每个逻辑结构的关系,从大到小的顺序为:表空间à段à区间à块。
?
?
?
?
?
?
第二部分:ORACLE9i新特性
9i创建数据库的工具改名为DBCA,也可以通过脚本更轻松容易的创建数据库,如:
create database ${ORACLE_SID}
user sys identified by sys
user system identified by system
logfile group 1 ('${ORACLE_BASE}/oradata/${ORACLE_SID}/redo01.log') size 10M ,
group 2 ('${ORACLE_BASE}/oradata/${ORACLE_SID}/redo02.log') size 10M ,
group 3 ('${ORACLE_BASE}/oradata/${ORACLE_SID}/redo03.log') size 10M
maxlogfiles 5
maxlogmembers 5
maxloghistory 1
maxdatafiles 254
maxinstances 1
archivelog
character set ZHS16GBK
national character set AL16UTF16
datafile '${ORACLE_BASE}/oradata/${ORACLE_SID}/system01.dbf' size 300M
default temporary tablespace tbstemp tempfile
??'${ORACLE_BASE}/oradata/${ORACLE_SID}/temp01.dbf' size 500M
undo tablespace tbsundo datafile
'${ORACLE_BASE}/oradata/${ORACLE_SID}/undo01.dbf' size 500M ;
其特点为使用专用的回滚和临时表空间,而不象Oracle 8i中的那样,回滚和临时表空间与普通表空间没有差异,这样既简化了配置也有利于效能提高。要注意临时表空间的指定文件关键字是tempfile而不是通用的datafile,而且临时表空间的存储选项由Oracle系统决定。同样回滚表空间也是由Oracle系统决定,不必人工干预。
Oracle 9i在$ORACLE_HOME/dbs下可使用二进制配置文件,缺省为spfile{SID}.ora,如spfileoradb.ora,支持Oracle系统进程在不重启的情况下动态调整参数,这对要求不间断运行的系统是有利的。在建库阶段就可将此配置文件创建起来。
create spfile from pfile;
or
create spfile=’文件全名’ from pfile=’文件全名’
数据库在启动的时候,会默认在$ORACLE_HOME/dbs找spfile{实例名}.ora文件,如果没有,它将寻找pfile文件,就是与8i兼容的init{SID}.ora的文本文件。当然,也可以通过指定的方式启动数据库。
Startup pfile=’文件全名’ or startup spfile=’文件全名’
使用spfile最大的好处可能就是支持动态的参数修改,如
alter system set parameter_name=new_value scope=memory|spfile|both
这样,通过命令方式可以修改参数生效或到参数文件。对于24*7的系统来说,这是一个不小的好处。
ORACLE9i中可以动态分配SGA,但是也是有限制的,你可以但分配SGA_MAX_SIZE大小,在这个尺寸之内,SGA的大小是可以动态分配的,可以根据不同的使用要求,来分配不同的SGA内存大小。
如
SQL> show parameter sga_max_size
?
NAME???????????????????????????? TYPE??????? VALUE
------------------------------------ ----------- --------------
sga_max_size???????????????????? ????big integer 1605044320?? //单位为字节
?
SQL> show parameter db_cache_size
?
NAME???????????????????????????? TYPE??????? VALUE
------------------------------------ ----------- ---------
db_cache_size??????????????????????? big integer 671088640
?
SQL> alter system set db_cache_size= 500M scope=both;
System altered.
注:db_cache_size也是9i新增加的参数,代替了以前版本中的db_block_buffers,可以通过该参数直接设置数据缓冲区的大小。
在9i以前,PGA主要包括用户信息,session信息,堆栈信息和Sort_Area_Size, Hash_Area_Size, Bitmap_Merge_Size, Create_Bitmap_Area_Size等池的大小。我们必须设置以上池的大小并监控它以获得最佳性能。
但是,在9i以后,我们可以通过设置以下两个参数以获得PGA的自动管理:
a. WORKAREA_SIZE_POLICY
b. PGA_AGGREGATE_TARGET
如果WORKAREA_SIZE_POLICY=true和PGA_AGGREGATE_TARGET=具体内存大小,ORACLE将自动管理PGA大大小,而忽略以上参数的设置。自动管理的PGA将采用自己的管理方法,可以获得PGA的共享使用。
如果采用了自动管理,将有如下视图可以监控
1.?????? V$SQL_WORKAREA
2.?????? V$SQL_WORKAREA_ACTIVE
3.?????? V$PROCESS contains new columns (PGA_USED_MEM, PGA_ALLOC_MEM AND PGA_MAX_MEM)
4.?????? V$PGASTAT
Oracle 9.2又增加了如下视图
1. V$SQL_WORKAREA_HISTOGRAM
2. V$PGA_TARGET_ADVICE
3. V$PGA_TARGET_ADVICE_HISTOGRAM
在9i,特别是920以后,如果系统表空间采用了本地管理,那所有的表空间都只能采用本地管理模式,如果显示指定字典管理将显示错误。其具体语法可以简单的描述为:
create tablespace tbsdata datafile '…' [ extent management local ] [ autoallocate ];
而对于指定每个扩展块大小的创建策略,设立了新选项:统一扩展块大小(uniform [size xxx[K|M]]),可覆盖autoallocate选项,如果不加上具体的size xxx[K|M],缺省为 1M ,这样就不必考虑Oracle 8i中的如initial,next,pctincrease,maxextents等default storage参数应如何组合,事实上Oracle 8i的这些设置原本就没有什么意义。
如果未指定extent management的类型,如果又同时使用default storage选项,为了兼容ORACLE8i,就有以下的判断:
如果使用minimun extent,Oracle检查是否minumum extent=initial=next且pctincrease=0,如是,Oracle使用uniform选项,size=initial;如不是,Oracle忽略指定选项,使用autoallocate。
如果未指定minimum extent,Oracle检查是否initial=next且pctincrease=0,如是Oracle使用uniform选项,size=initial;如不是Oracle忽略指定选项,使用autoallocate。
为了避免与Oracle 8i的习惯做法混淆,建议只使用Oracle 9i较简洁的方法。
对于存储少量静态数据的表空间来说,如配置信息等,可简单地写为:
create tablespace tbsdata datafile '…';
对于必须关心其扩展块大小的表空间,如大批量的记录或索引,可简单地写为:
create tablespace tbsdata datafile '…' uniform size 10M ;
另外一个问题就是,9i的临时表空间将全部采用本地管理模式,所以在ORACLE8i往上升级的时候,临时表空间将会出错,因为ORACLE这里没有提供向下的兼容性。
创建临时表空间的语法在9i中被改为如下:
create temporary tablespace tempfile ‘文件全名’
在9i以前,回滚段全是手工管理与监控的,DBA需要花费一定的时间去管理与监控回滚段的性能,创建不好或管理不好的回滚段,将引起很大的性能瓶颈。从ORACLE9i,为了更好的管理回滚段,ORACLE,默认采用自动回滚段管理。
自动回滚段管理可以最大限度的避免8i中比较有名的“快照太老”的错误,ORACLE9i通过如下四个初试化参数来设置自动回滚段管理:
undo_management??????????????????? string????? AUTO
undo_retention?????????????????????? integer???? 10800
undo_suppress_errors???????????????? boolean???? FALSE
undo_tablespace????????????????????? string????? UNDOTBS1
undo_management表明了回滚段管理采用自动方式,ORACLE建议采用自动方式,如果不是对数据库非常了解,不要修改该参数。
undo_retention表明了回滚信息在回滚段中保持的时间,单位是秒,默认3个小时。
undo_suppress_errors表明不显示某些错误信息,如对系统回滚段的操作将不显示错误,虽然这个操作没有成功。
undo_tablespace表明了使用自动回滚的表空间,DBA需要监控该表空间的大小。
自动回滚段的另外一个好处就是可以利用flashback来查看提交以前的数据或导出提交以前的数据,防止一定程度上的人为错误。
ORACLE9i引进了段空间的自动分配(ASSM),ASSM的tablespace是通过将SEGMENT SPACE MANAGEMENT AUTO子句添加到tablespace的定义句法里而实现的(只能是本地管理的表空间)。通过使用位图freelist取代传统单向的链接列表freelist,ASSM的tablespace会将freelist的管理自动化,并取消为独立的表格和索引指定PCTUSED、FREELISTS和FREELIST GROUPS存储参数的能力。
要注意,当表或者索引被分配到这个tablespace以后,用于独立对象的PCTUSED的值会被忽略,而Oracle9i会使用位图数组来自动地管理tablespace里表格和索引的freelist。对于在LMT的tablespace内部创建的表格和索引而言,这个NEXT扩展子句是过时的,因为由本地管理的tablespace会管理它们。但是,INITIAL参数仍然是需要的,因为Oracle不可能提前知道初始表格加载的大小。对于ASSM而言,INITIAL最小的值是三个区块。
关于一个万能的方法对于Oracle来说是否是最好的方法还有一些争论。在大型数据库里,单独的对象设置会带来性能和存储上的巨大不同。
在以前的版本中,在没有多个freelist的时候,每个Oracle表格和索引在表格的头部都曾有一个数据块,用来管理对象所使用的剩余区块,并为任何SQL插入声明所创建的新数据行提供数据块。当数据缓冲内的数据块由于被另一个DML事务处理锁定而无法使用的时候,缓冲区忙等待就会发生。当你需要将多个任务插入到同一个表格里的时候,这些任务就被强制等待,而同时Oracle会在同时分派剩余的区块,一次一个。
有了ASSM之后,Oracle宣称显著地提高了DML并发操作的性能,因为(同一个)位图的不同部分可以被同时使用,这样就消除了寻找剩余空间的串行化。根据Oracle的测试结果,使用位图freelist会消除所有分段头部(对资源)的争夺,还能获得超快的并发插入操作
?
http://www.happyit.net
http://otn.oracle.com/documentation/content.html
http://metalink.oracle.com/
Expert One-on-one Oracle? [美] Thomas Kyte 著 清华大学出版社
Oracle 8i Web开发指南 [美] Dan Hotka,et al. 著 清华大学出版社
Oracle 8i DBA Architecture & Administration and backup & Recovery Study Guide
????????????????????????????? [美] Dong Stuns Biju Thomas著 电子工业出版社
Oracle 数据库管理员技术指南 [美] Sumit Sarin著 机械工业出版社
ORACLE 9i UNIX 管理手册 [美] Donald K.Burleson 著 机械工业出版社
?
2004 -8-6
联合查询
UNION运算可以把多个查询的结果合并到一个结果集里显示.
UNION运算的一般语法:
[表]查询1UNION[ALL]查询2 UNION …
例:返回巴西所有供给商和客户的名字和城市
SELECT CompanyName,City
FROMSuppliers
WHERE Country = ‘Brazil’
UNION
SELECT CompanyName,City
FROMCustomers
WHERE Country = ‘Brazil’
注:
缺省的情况下,UNION子句不返回重复的记录.如果想显示所有记录,可以加ALL选项
UNION运算要求查询具有相同数目的字段.但是,字段数据类型不必相同.
每一个查询参数中可以使用GROUP BY 子句 或 HAVING 子句进行分组.要想以指定的顺序来显示返回的数据,可以在最后一个查询的尾部使用OREER BY子句.
如果两个表,例如supply和custom表,他们的列名必须相同才可用UNION函数,否则不可以用。如果列名相同,但数据类型不同,则也可以执行union函数,但会重复的列出J
?
?
内连接时,返回查询结果集合中的仅是符合查询条件( WHERE 搜索条件或 HAVING 条件)和连接条件
的行。而采用外连接时,它返回到查询结果集合中的不仅包含符合连接条件的行,而且还包括左表(左外
连接时)、右表(右外连接时)或两个边接表(全外连接)中的所有数据行。
?
例如两个表supply和custom
SQL> select * from supply;
?
COMPANYN CITY
-------- --------
IBM????? manhaton
HP?????? newyork
MS?????? newyork
?
SQL> select * from custom;
?
COMPANYN CITY
-------- --------
IBM????? manhaton
MS?????? manhaton
SUN????? kalifnio
?
SQL> select * from supply union select * from custom;
?
COMPANYN CITY
-------- --------
HP?????? newyork
IBM????? manhaton
MS?????? manhaton
MS?????? newyork
SUN????? kalifnio
?
SQL> select * from supply s left join custom c on s.COMPANYNAME=c.COMPANYNAME;
?
COMPANYN CITY ???? COMPANYN CITY
-------- -------- -------- --------
IBM????? manhaton IBM????? manhaton
MS?????? newyork? MS?????? manhaton
HP?????? newyork
SQL> select * from supply s,custom c where s.COMPANYNAME=c.COMPANYNAME(+);
?
COMPANYN CITY ???? COMPANYN CITY
-------- -------- -------- --------
HP?????? newyork
IBM????? manhaton IBM????? manhaton
MS?????? newyork? MS?????? manhaton
?
SQL> select * from supply s full outer join custom c on s.city=c.city;
?
COMPANYN CITY ???? COMPANYN CITY
-------- -------- -------- --------
IBM????? manhaton IBM????? manhaton
IBM????? manhaton MS?????? manhaton
MS?????? newyork
HP?????? newyork
????????????????? SUN????? kalifnio
?
SQL> select * from supply cross join custom;
?
COMPANYN CITY ???? COMPANYN CITY
-------- -------- -------- --------
IBM????? manhaton IBM????? manhaton
HP?????? newyork? IBM????? manhaton
MS?????? newyork? IBM????? manhaton
IBM????? manhaton MS?????? manhaton
HP?????? newyork? MS?????? manhaton
MS?????? newyork? MS?????? manhaton
IBM????? manhaton SUN????? kalifnio
HP? ?????newyork? SUN????? kalifnio
MS?????? newyork? SUN????? kalifnio
?
已选择9行。
?
SQL> select * from supply s inner join custom c on s.COMPANYNAME=c.COMPANYNAME;
?
COMPANYN CITY ???? COMPANYN CITY
-------- -------- -------- --------
IBM????? manhaton IBM????? manhaton
MS?????? newyork? MS?????? manhaton
?