数据库原理及应用试题

数据库原理及应用试题,第1张

1.B 2.C 3.B 4.C 5.D 6.C 7.C 8.D 9.C 10.A

11.A 12.A 13.A --不太确定 14.B 15.C 16.A 17.B 18.A 19.D 20.C

1.试述事务的概念及事务的四个特性。

答:

事务是用户定义的一个数据库 *** 作序列,这些 *** 作要么全做要么全不做,是一个不可分割的工作单位。

事务具有四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持续性(Durability)。这个四个特性也简称为ACID特性。

原子性:事务是数据库的逻辑工作单位,事务中包括的诸 *** 作要么都做,要么都不做。

一致性:事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。

隔离性:一个事务的执行不能被其他事务干扰。即一个事务内部的 *** 作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能互相干扰。

持续性:持续性也称永久性(Permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他 *** 作或故障不应该对其执行结果有任何影响。

2.为什么事务非正常结束时会影响数据库数据的正确性,请列举一例说明之。

答:

事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。如果数据库系统运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是不一致的状态。

例如某工厂的库存管理系统中,要把数量为Q的某种零件从仓库1移到仓库2存放。

则可以定义一个事务T,T包括两个 *** 作;Q1=Q1-Q,Q2=Q2+Q。如果T非正常终止时只做了第一个 *** 作,则数据库就处于不一致性状态,库存量无缘无故少了Q。

3.数据库中为什么要有恢复子系统?它的功能是什么?

答:

因为计算机系统中硬件的故障、软件的错误、 *** 作员的失误以及恶意的破坏是不可避免的,这些故障轻则造成运行事务非正常中断,影响数据库中数据的正确性,重则破坏数据库,使数据库中全部或部分数据丢失,因此必须要有恢复子系统。

恢复子系统的功能是:把数据库从错误状态恢复到某一已知的正确状态(亦称为一致状态或完整状态)。

4.数据库运行中可能产生的故障有哪几类?哪些故障影响事务的正常执行?哪些故障破坏数据库数据?

答:数据库系统中可能发生各种各样的故障,大致可以分以下几类:

(1)事务内部的故障;

(2)系统故障;

(3)介质故障;

(4)计算机病毒。

事务故障、系统故障和介质故障影响事务的正常执行;介质故障和计算机病毒破坏数据

库数据。

5.据库恢复的基本技术有哪些?

答:

数据转储和登录日志文件是数据库恢复的基本技术。

当系统运行过程中发生故障,利用转储的数据库后备副本和日志文件就可以将数据库恢复到故障前的某个一致性状态。

6. 数据库转储的意义是什么? 试比较各种数据转储方法。

答:

数据转储是数据库恢复中采用的基本技术。所谓转储即DBA定期地将数据库复制到磁带或另一个磁盘上保存起来的过程。当数据库遭到破坏后可以将后备副本重新装入,将数据库恢复到转储时的状态。

静态转储:在系统中无运行事务时进行的转储 *** 作。静态转储简单,但必须等待正运行的用户事务结束才能进行。同样,新的事务必须等待转储结束才能执行。显然,这会降低数据库的可用性。

动态转储:指转储期间允许对数据库进行存取或修改。动态转储可克服静态转储的缺点,它不用等待正在运行的用户事务结束,也不会影响新事务的运行。但是,转储结束时后援副本上的数据并不能保证正确有效。因为转储期间运行的事务可能修改了某些数据,使得后援副本上的数据不是数据库的一致版本。

为此,必须把转储期间各事务对数据库的修改活动登记下来,建立日志文件(log file)。这样,后援副本加上日志文件就能得到数据库某一时刻的正确状态。

转储还可以分为海量转储和增量转储两种方式。

海量转储是指每次转储全部数据库。增量转储则指每次只转储上一次转储后更新过的数据。从恢复角度看,使用海量转储得到的后备副本进行恢复一般说来更简单些。但如果数据库很大,事务处理又十分频繁,则增量转储方式更实用更有效。

7. 什么是日志文件?为什么要设立日志文件?

答:

(1)日志文件是用来记录事务对数据库的更新 *** 作的文件。

(2)设立日志文件的目的是: 进行事务故障恢复;进行系统故障恢复;协助后备副本进行介质故障恢复。

8. 登记日志文件时为什么必须先写日志文件,后写数据库?

答:

把对数据的修改写到数据库中和把表示这个修改的日志记录写到日志文件中是两个不同的 *** 作。有可能在这两个 *** 作之间发生故障,即这两个写 *** 作只完成了一个。

如果先写了数据库修改,而在运行记录中没有登记这个修改,则以后就无法恢复这个修改了。如果先写日志,但没有修改数据库,在恢复时只不过是多执行一次UNDO *** 作,并不会影响数据库的正确性。所以一定要先写日志文件,即首先把日志记录写到日志文件中,然后写数据库的修改。

9. 针对不同的故障,试给出恢复的策略和方法。(即如何进行事务故障的恢复?系统故障的恢复?介质故障恢复?)

答:

事务故障的恢复:

事务故障的恢复是由DBMS自动完成的,对用户是透明的。

DBMS执行恢复步骤是:

(1)反向扫描文件日志(即从最后向前扫描日志文件),查找该事务的更新 *** 作。

(2)对该事务的更新 *** 作执行逆 *** 作。即将日志记录中“更新前的值”写入数据库。

(3)继续反向扫描日志文件,做同样处理。

(4)如此处理下去,直至读到此事务的开始标记,该事务故障的恢复就完成了。

答:

系统故障的恢复:

系统故障可能会造成数据库处于不一致状态:

一是未完成事务对数据库的更新可能已写入数据库;

二是已提交事务对数据库的更新可能还留在缓冲区,没来得及写入数据库。

因此恢复 *** 作就是要撤销(UNDO)故障发生时未完成的事务,重做(REDO)已完成的事务。

系统的恢复步骤是:

(1)正向扫描日志文件,找出在故障发生前已经提交的事务队列(REDO队列)和未完成的事务队列(UNDO队列)。

(2)对撤销队列中的各个事务进行UNDO处理。

进行UNDO处理的方法是,反向扫描日志文件,对每个UNDO事务的更新 *** 作执行逆 *** 作,即将日志记录中“更新前的值”(Before Image)写入数据库。

(3)对重做队列中的各个事务进行REDO处理。

进行REDO处理的方法是:正向扫描日志文件,对每个REDO事务重新执行日志文件登记的 *** 作。即将日志记录中“更新后的值”(After Image)写入数据库。

*解析:

在第(1)步中如何找出REDO队列和UNDO队列?请大家思考一下。

下面给出一个算法:

1) 建立两个事务队列:

· UNDO-LIST: 需要执行undo *** 作的事务集合;

· REDO-LIST: 需要执行redo *** 作的事务集合;

两个事务队列初始均为空。

2) 从日志文件头开始,正向扫描日志文件

· 如有新开始(遇到Begin Transaction)的事务Ti,把Ti暂时放入UNDO-LIST队列;

· 如有提交的事务(遇到End Transaction)Tj,把Tj从UNDO-LIST队列移到REDO-LIST队列;

直到日志文件结束

答:

介质故障的恢复:

介质故障是最严重的一种故障。

恢复方法是重装数据库,然后重做已完成的事务。具体过程是:

(1)DBA装入最新的数据库后备副本(离故障发生时刻最近的转储副本),使数据库恢复到转储时的一致性状态。

(2)DBA装入转储结束时刻的日志文件副本

(3)DBA启动系统恢复命令,由DBMS完成恢复功能,即重做已完成的事务。

*解析

1)我们假定采用的是静态转储,因此第(1)步装入数据库后备副本便可以了。

2)如果采用的是静动态转储,第(1)步装入数据库后备副本还不够,还需同时装入转储开始时刻的日志文件副本,经过处理后才能得到正确的数据库后备副本。

3)第(2)步重做已完成的事务的算法是:

a. 正向扫描日志文件,找出故障发生前已提交的事务的标识,将其记入重做队列

b. 再一次正向扫描日志文件,对重做队列中的所有事务进行重做处理。即将日志记录中“更新后的值”写入数据库。

10. 具有检查点的恢复技术有什么优点?

答:

利用日志技术进行数据库恢复时,恢复子系统必须搜索日志,确定哪些事务需要REDO,哪些事务需要UNDO。一般来说,需要检查所有日志记录。这样做有两个问题:

一是搜索整个日志将耗费大量的时间。

二是很多需要REDO处理的事务实际上已经将它们的更新 *** 作结果写到数据库中了,恢复子系统又重新执行了这些 *** 作,浪费了大量时间。

检查点技术就是为了解决这些问题。

11. 试述使用检查点方法进行恢复的步骤。

答:

① 从重新开始文件中找到最后一个检查点记录在日志文件中的地址,由该地址在日志文件中找到最后一个检查点记录。

② 由该检查点记录得到检查点建立时刻所有正在执行的事务清单ACTIVE-LIST。

这里建立两个事务队列:

· UNDO-LIST: 需要执行undo *** 作的事务集合;

· REDO-LIST: 需要执行redo *** 作的事务集合;

把ACTIVE-LIST暂时放入UNDO-LIST队列,REDO队列暂为空。

③ 从检查点开始正向扫描日志文件

· 如有新开始的事务Ti,把Ti暂时放入UNDO-LIST队列;

· 如有提交的事务Tj,把Tj从UNDO-LIST队列移到REDO-LIST队列,直到日志文件结束;

④ 对UNDO-LIST中的每个事务执行UNDO *** 作, 对REDO-LIST中的每个事务执行REDO *** 作。

12. 什么是数据库镜像?它有什么用途?

答:

数据库镜像即根据DBA的要求,自动把整个数据库或者其中的部分关键数据复制到另一个磁盘上。每当主数据库更新时,DBMS自动把更新后的数据复制过去,即DBMS自动保证镜像数据与主数据的一致性。

数据库镜像的用途有:

一是用于数据库恢复。当出现介质故障时,可由镜像磁盘继续提供使用,同时DBMS自动利用镜像磁盘数据进行数据库的恢复,不需要关闭系统和重装数据库副本。

二是提高数据库的可用性。在没有出现故障时,当一个用户对某个数据加排它锁进行修改时,其他用户可以读镜像数据库上的数据,而不必等待该用户释放锁。

1、 ORACLE 实例――包括内存结构与后台进程 2、 ORACLE 数据库――物理 *** 作系统文件的集合 3、 了解内存结构的组成 4、 了解后台进程的作用

1、 Oracle 实例――包括内存结构与后台进程

2、 Oracle 数据库――物理 *** 作系统文件的集合

3、 了解内存结构的组成

4、 了解后台进程的作用

5、 了解数据库的物理文件

6、 解释各种逻辑结构

一、Oracle实例

1、Oracle 实例

System Global Area(SGA) 和 Background Process 称为数据库的实例。

2、Oracle 数据库

一系列物理文件的集合(数据文件,控制文件,联机日志,参数文件等)

3、系统全局共享区System Global Area(SGA)

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

主要包括以下几个部分:

a、 共享池(Shared pool)

共享池是SGA中最关键的内存片段,特别是在性能和可伸缩性上。一个太小的共享池会扼杀性能,使系统停止,太大的共享池也会有同样的效果,将会消耗大量的CPU来管理这个共享池。不正确的使用共享池只会带来灾难。共享池主要又可以分为以下两个部分:

SQL语句缓冲(Library Cache)

当一个用户提交一个SQL语句,Oracle会将这句SQL进行分析(parse),这个过程类似于编译,会耗费相对较多的时间。在分析完这个SQL,Oracle会把他的分析结果给保存在Shared pool的Library Cache中,当数据库第二次执行该SQL时,Oracle自动跳过这个分析过程,从而减少了系统运行的时间。这也是为什么第一次运行的SQL 比第二次运行的SQL要慢一点的原因。

下面举例说明parse的时间

SQL>select count(*) fromscpass

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 scpass

COUNT(*)

----------

243

Elapsed: 00:00:00.02

SQL>select count(*) from scpass

COUNT(*)

----------

243

Elapsed: 00:00:00.00

从两句SQL 的时间差上可以看出该SQL 的Parse 时间约为00:00:00.02

对于保存在共享池中的SQL语句,可以从V$Sqltext、v$Sqlarea中查询到,对于编程者来说,要尽量提高语句的重用率,减少语句的分析时间。一个设计的差的应用程序可以毁掉整个数据库的Share pool,提高SQL语句的重用率必须先养成良好的变成习惯,尽量使用Bind变量。

数据字典缓冲区(Data Dictionary Cache)

显而易见,数据字典缓冲区是Oracle特地为数据字典准备的一块缓冲池,供Oracle内部使用,没有什么可以说的。

b、块缓冲区高速缓存(Database Buffer Cache)

这些缓冲是对应所有数据文件中的一些被使用到的数据块。让他们能够在内存中进行 *** 作。在这个级别里没有系统文件,,户数据文件,临时数据文件,回滚段文件之分。也就是任何文件的数据块都有可能被缓冲。数据库的任何修改都在该缓冲里完成,并由DBWR进程将修改后的数据写入磁盘。

这个缓冲区的块基本上在两个不同的列表中管理。一个是块的“脏”表(Dirty List),需要用数据库块的

书写器(DBWR)来写入,另外一个是不脏的块的列表(Free List),一般的情况下,是使用最近最少使用 (Least Recently Used,LRU)算法来管理。块缓冲区高速缓存又可以细分为以下三个部分(Default pool,Keep pool,Recycle pool)。如果不是人为设置初始化参数(Init.ora),Oracle将默认为Default pool。由于 *** 作系统寻址能力的限制,不通过特殊设置,在32位的系统上,块缓冲区高速缓存最大可以达到1.7G,在64位系统上,块缓冲区高速缓存最大可以达到10G。

c、重做日志缓冲区(Redo log buffer)

重做日志文件的缓冲区,对数据库的任何修改都按顺序被记录在该缓冲,然后由LGWR进程将它写入磁盘。这些修改信息可能是DML语句,如(Insert,Update,Delete),或DDL语句,如(Create,Alter,Drop等)。 重做日志缓冲区的存在是因为内存到内存的 *** 作比较内存到硬盘的速度快很多,所以重作日志缓冲区可以加快数据库的 *** 作速度,但是考虑的数据库的一致性与可恢复性,数据在重做日志缓冲区中的滞留时间不会很长。所以重作日志缓冲区一般都很小,大于3M之后的重作日志缓冲区已经没有太大的实际意义。

d、Java程序缓冲区(Java Pool)

Java 的程序区,Oracle 8I 以后,Oracle 在内核中加入了对Java的支持。该程序缓冲区就是为Java 程序保留的。如果不用Java程序没有必要改变该缓冲区的默认大小。

e、大池(Large Pool)

大池的得名不是因为大,而是因为它用来分配大块的内存,处理比共享池更大的内存,在8.0开始引入。

下面对象使用大池:

MTS――在SGA的Large Pool中分配UGA

语句的并行查询(Parallel Executeion of Statements)――允许进程间消息缓冲区的分配,用来协调 并行查询服务器

备份(Backup)――用于RMAN磁盘I/O缓存

4、后台进程(Background process)

后台进程是Oracle的程序,用来管理数据库的读写,恢复和监视等工作。Server Process主要是通过他和user process进行联系和沟通,并由他和user process进行数据的交换。在Unix机器上,Oracle后台进程相对于 *** 作系统进程,也就是说,一个Oracle后台进程将启动一个 *** 作系统进程;在Windows机器上, Oracle后台进程相对于 *** 作系统线程,打开任务管理器,我们只能看到一个Oracle.EXE的进程,但是通过另外的工具,就可以看到包含在这里进程中的线程。

在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

a、Oracle系统有5 个基本进程他们是

DBWR(数据文件写入进程)

LGWR(日志文件写入进程)

SMON(系统监护进程)

PMON(用户进程监护进程)

CKPT(检查点进程,同步数据文件, 日志文件,控制文件)

b、DBWR

将修改过的数据缓冲区的数据写入对应数据文件

维护系统内的空缓冲区

这里指出几个容易错误的概念:

当一个更新提交后,DBWR把数据写到磁盘并返回给用户提交完成.

DBWR会触发CKPT 后台进程

DBWR不会触发LGWR 进程

上面的概念都是错误的.

DBWR是一个很底层的工作进程,他批量的把缓冲区的数据写入磁盘。和任何前台用户的进程几乎没有什么关系,也不受他们的控制。至于DBWR会不会触发LGWR和CKPT进程,我们将在下面几节里讨论。

DBWR工作的主要条件如下

DBWR 超时

系统中没有多的空缓冲区用来存放数据

CKPT 进程触发DBWR 等

c、LGWR

将重做日志缓冲区的数据写入重做日志文件,LGWR是一个必须和前台用户进程通信的进程。当数据被修改的时候,系统会产生一个重做日志并记录在重做日志缓冲区内。这个重做日志可以类似的认为是以下的一个结构:

SCN=000000001000

数据块ID

对象ID=0801

数据行=02

修改后的数据=0011

提交的时候,LGWR必须将被修改的数据的重做日志缓冲区内数据写入日志数据文件,然后再通知前台进程提交成功,并由前台进程通知用户。从这点可以看出LGWR承担了维护系统数据完整性的任务。

LGWR 工作的主要条件如下

用户提交

有1/3 重做日志缓冲区未被写入磁盘

有大于1M 重做日志缓冲区未被写入磁盘

超时

DBWR需要写入的数据的SCN号大于LGWR 记录的SCN号,DBWR 触发LGWR写入

d、SMON

工作主要包含

清除临时空间

在系统启动时,完成系统实例恢复

聚结空闲空间

从不可用的文件中恢复事务的活动

OPS中失败节点的实例恢复

清除OBJ$表

缩减回滚段

使回滚段脱机

e、PMON

主要用于清除失效的用户进程,释放用户进程所用的资源。如PMON将回滚未提交的工作,释放锁,释放分配给失败进程的SGA资源。

f、CKPT

同步数据文件,日志文件和控制文件,由于DBWR/LGWR的工作原理,造成了数据文件,日志文件,控制文件的不一至,这就需要CKPT进程来同步。CKPT会更新数据文件/控制文件的头信息。

CKPT工作的主要条件如下

在日志切换的时候

数据库用immediate ,transaction , normal 选项shutdown 数据库的时候

根据初始话文件LOG_CHECKPOINT_INTERVAL、LOG_CHECKPOINT_TIMEOUT、FAST_START_IO_TARGET 的设置的数值来确定

用户触发

以下进程的启动需要手工配置

g、ARCH

当数据库以归档方式运行的时候,Oracle会启动ARCH进程,当重做日志文件被写满时,日志文件进行切换,旧的重做日志文件就被ARCH进程复制到一个/多个特定的目录/远程机器。这些被复制的重做日志文件被叫做归档日志文件。

h、RECO

负责解决分布事物中的故障。Oracle可以连接远程的多个数据库,当由于网络问题,有些事物处于悬而未决的状态。RECO进程试图建立与远程服务器的通信,当故障消除后,RECO进程自动解决所有悬而未决的会话。

i、服务进程Server Process

服务进程的分类

专用服务进程(Dedicated Server Process)

一个服务进程对应一个用户进程

共享服务进程(MultiTreaded Server Process)

一个服务进程对应多个用户进程,轮流为用户进程服务。

PGA &UGA

PGA = Process Global Area

UGA = User Global Area

他保存了用户的变量、权限、堆栈、排序空间等用户信息,对于专用服务器进程,UGA在PGA中分配。对于多线程进程,UGA在Large pool中分配。

j、用户进程User Process

在客户端,将用户的SQL 语句传递给服务进程

5、一个贯穿数据库全局的概念----系统改变号SCN(System Change Number)

系统改变号,一个由系统内部维护的序列号。当系统需要更新的时候自动增加,他是系统中维持数据的一致性和顺序恢复的重要标志。

a. 查询语句不会使SCN增加,就算是同时发生的更新,数据库内部对应的SCN也是不同的。这样一来就保证了数据恢复时候的顺序。

b. 维持数据的一致性,当一

二、Oracle 数据库

Oracle数据库的组成――物理 *** 作系统文件的集合。主要包括以下几种。

1、控制文件(参数文件init.ora记录了控制文件的位置)

控制文件包括如下主要信息

数据库的名字,检查点信息,数据库创建的时间戳

所有的数据文件,联机日志文件,归档日志文件信息

备份信息等

有了这些信息,Oracle就知道那些文件是数据文件,现在的重做日志文件是哪些,这些都是系统启动和运行的基本条件,所以他是Oracle运行的根本。如果没有控制文件系统是不可能启动的。控制文件是非常重要的,一般采用多个镜相复制来保护控制文件,或采用RAID来保护控制文件。控制文件的丢失,将使数据库的恢复变的很复杂。

控制文件信息可以从V$Controlfile中查询获得

2、数据文件(数据文件的详细信息记载在控制文件中)

可以通过如下方式查看数据文件

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

从以上可以看出,数据文件大致可以分为以下几类:

i. 系统数据文件(system_01.dbf)

存放系统表和数据字典,一般不放用户的数据,但是用户脚本,如过程,函数,包等却是保存在数据字典中的。

名词解释:数据字典 数据字典是一些系统表或视图,他存放系统的信息,他包括数据库版本,数据文件信息,表与索引等段信息,系统的运行状态等各种和系统有关的信息和用户脚本信息。数据库管理员可以通过对数据字典的查询,就可以了解到Oracle的运行状态。

ii. 回滚段文件(rbs_01.dbf)

如果数据库进行对数据的修改,那么就必须使用回滚段,回滚段是用来临时存放修改前的数据(Before Image)。回滚段通常都放在一个单独的表空间上(回滚表空间),避免表空间碎片化,这个表空间包含的数据文件就是回滚数据文件。

iii. 临时数据文件(temp_01.dbf)

主要存放用户的排序等临时数据,与回滚段相似,临时段也容易引起表空间碎片化,而且没有办法在一个永久表空间上开辟临时段,所以就必须有一个临时表空间,它所包含的数据文件就是临时数据文件,主要用于不能在内存上进行的排序 *** 作。我们必须为用户指定一个临时表空间。

iv. 用户数据文件(/applsys_data_01.dbf ,applsys_indx_01.dbf)

存放用户数据,这里列举了两类常见的用户型数据,一般数据和索引数据,一般来说,如果条件许可的话,可以考虑放在不同的磁盘上。

3、重做日志文件(联机重做日志)

用户对数据库进行的任何 *** 作都会记录在重做日志文件。在了解重做日志之前必须了解重做日志的两个概念,重做日志组和重做日志组成员(Member),一个数据库中至少要有两个日志组文件,一组写完后再写另一组,即轮流写。每个日志组中至少有一个日志成员,一个日志组中的多个日志成员是镜相关系,有利于日志文件的保护,因为日志文件的损坏,特别是当前联机日志的损坏,对数据库的影响是巨大的。

联机日志组的交换过程叫做切换,需要特别注意的是,日志切换在一个优化效果不好的数据库中会引起临时的“挂起”。挂起大致有两种情况:

在归档情况下,需要归档的日志来不及归档,而联机日志又需要被重新利用

检查点事件还没有完成(日志切换引起检查点),而联机日志需要被重新利用

解决这种问题的常用手段是:

i.增加日志组

ii.增大日志文件成员大小

通过v$log可以查看日志组,v$logfile可以查看具体的成员文件。

4、归档日志文件

Oracle可以运行在两种模式之中,归档模式和不归档模式。如果不用归档模式,当然,你就不会有归档日志,但是,你的系统将不会是一个实用系统,特别是不能用于生产系统,因为你可能会丢失数据。但是在归档模式中,为了保存用户的所有修改,在重做日志文件切换后和被覆盖之间系统将他们另外保存成一组连续的文件系列,该文件系列就是归档日志文件。

有人或许会说,归档日志文件占领我大量的硬盘空间,其实,具体想一想,你是愿意浪费一点磁盘空间来保护你的数据,还是愿意丢失你的数据呢?显而义见,我们需要保证我们的数据的安全性。其实,归档并不是一直占领你的磁盘空间,你可以把她备份到磁带上,或则删除上一次完整备份前的所有日志文件。

5、初始化参数文件

initSID.ora或init.ora文件,因为版本的不一样,其位置也可能会不一样。在8i中,通常位于$Oracle_HOME/admin//Pfile下,初始化文件记载了许多数据库的启动参数,如内存,控制文件,进程数等,在数据库启动的时候加载(Nomount时加载),初始化文件记录了很多重要参数,对数据库的性能影响很大,如果不是很了解,不要轻易乱改写,否则会引起数据库性能下降。

6、其他文件

i . 密码文件

用于Oracle 的具有sysdba权限用户的认证.

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"

三、Oracle逻辑结构

1、 表空间(tablespace)

表空间是数据库中的基本逻辑结构,一系列数据文件的集合。一个表空间可以包含多个数据文件,但是一个数据文件只能属于一个表空间。

2、 段(Segment)

段是对象在数据库中占用的空间,虽然段和数据库对象是一一对应的,但段是从数据库存储的角度来看的。一个段只能属于一个表空间,当然一个表空间可以有多个段。

表空间和数据文件是物理存储上的一对多的关系,表空间和段是逻辑存储上的一对多的关系,段不直接和数据文件发生关系。一个段可以属于多个数据文件,关于段可以指定扩展到哪个数据文件上面。

段基本可以分为以下四种

数据段(Data Segment)

索引段(Index Segment)

回滚段(Rollback Segment)

临时段(Temporary Segment)

3、区间(Extent)

关于Extent的翻译有多种解释,有的译作扩展,有的译作盘区,我这里通常译为区间。在一个段中可以存在多个区间,区间是为数据一次性预留的一个较大的存储空间,直到那个区间被用满,数据库会继续申请一个新的预留存储空间,即新的区间,一直到段的最大区间数(Max Extent)或没有可用的磁盘空间可以申请。 在Oracle8i以上版本,理论上一个段可以无穷个区间,但是多个区间对Oracle却是有性能影响的,Oracle建议把数据分布在尽量少的区间上,以减少Oracle的管理与磁头的移动。

4、Oracle数据块(Block)

Oracle最基本的存储单位,他是OS数据块的整数倍。Oracle的 *** 作都是以块为基本单位,一个区间可以包含多个块(如果区间大小不是块大小的整数倍,Oracle实际也扩展到块的整数倍)。

5、基本表空间介绍

a. 系统表空间

主要存放数据字典和内部系统表基表

查看数据数据字典的SQL

select * from dict

查看内部系统表的SQL

select * from v$fixed_view_definition

DBA对系统的系统表中的数据字典必须有一个很深刻的了解,他们必须准备一些基础的SQL语句,通过这些SQL可以立即了解系统的状况和数据库的状态,这些基本的SQL包括

系统的剩余空间

系统的SGA

状态系统的等待

用户的权限

当前的用户锁

缓冲区的使用状况等

在成为DBA 的道路上我们不建议你过分的依赖于OEM/Quest 等优秀的数据库管理工具,因为他们不利于你对数据数据字典的理解,SQL语句可以完成几乎全部的数据库管理工作。

大量的读少量的写是该表空间的一个显著的特点。

b. 临时表空间.

临时表空间顾名思义是用来存放临时数据的,例如排序 *** 作的临时空间,他的空间会在下次系统启动的时候全部被释放。

c. 回滚段表空间

i. 回滚段在系统中的作用

当数据库进行更新插入删除等 *** 作的时候,新的数据被更新到原来的数据文件,而旧的数据(Before Image)就被放到回滚段中,如果数据需要回滚,那么可以从回滚段将数据再复制到数据文件中。来完成数据的回滚。在系统恢复的时候, 回滚段可以用来回滚没有被commit 的数据,解决系统的一至性。

回滚段在什么情况下都是大量的写,一般是少量读,因此建议把回滚段单独出来放在一个单独的设备(如单独的磁盘或RAID),以减少磁盘的IO争用。

ii. 回滚段的工作方式

一个回滚表空间可以被划分成多个回滚段.

一个回滚段可以保存多个会话的数据.

回滚段是一个圆形的数据模型

假设回滚段由4 个区间组成,他们的使用顺序就是区间1à区间2à区间3à区间4à区间1。也就是说,区间是可以循环使用的,当区间4到区间1的时候,区间1里面的会话还没有结束, 区间4用完后就不能再用区间1,这时系统必须分配区间5,来继续为其他会话服务服务。

我们分析一个Update 语句的完成

①. 用户提交一个Update 语句

②. Server Process 检查内存缓冲.

如果没有该数据块的缓冲,则从磁盘读入

i. 如果没有内存的有效空间,DBWR被启动将未写入磁盘的脏缓冲写入磁盘

ii. 如果有有效空间,则读入

③. 在缓冲内更新数据

i. 申请一个回滚段入口,将旧数据写如回滚段

ii. 加锁并更新数据

iii. 并在同时将修改记录在Redo log buffer中

DataReader 的默认行为是在整个数据行可用时立即以行的形式加载传入数据 但是 对于二进制大对象 (BLOB) 则需要进行不同的处理 因为它们可能包含数十亿字节的数据 而单个行中无法包含如此多的数据 Command ExecuteReader 方法具有一个重载 它将采用 CommandBehavior 参数来修改 DataReader 的默认行为 您可以将 CommandBehavior SequentialAccess 传递到 ExecuteReader 方法来修改 DataReader 的默认行为 以便让 DataReader 按照顺序在接收到数据时立即将其加载 而不是加载数据行 这是加载 BLOB 或其他大数据结构的理想方案 在将 DataReader 设置为使用 SequentialAccess 时 务必要注意访问所返回字段的顺序 DataReader 的默认行为是在整个行可用时立即加载该行 这使您能够在读取下一行之前按任何顺序访问所返回的字段 但是 当使用 SequentialAccess 时 必须按顺序访问由 DataReader 返回的不同字段 例如 如果查询返回三个列 其中第三列是 BLOB 则必须在访问第三个字段中的 BLOB 数据之前返回第一个和第二个字段的值 如果在访问第一个或第二个字段之前访问第三个字段 则第一个和第二个字段值将不再可用 这是因为 SequentialAccess 已修改 DataReader 使其按顺序返回数据 当 DataReader 已经读取超过特定数据时 该数据将不可用 当访问 BLOB 字段中的数据时 请使用 DataReader 的 GetBytes 类型化访问器 该访问器将使用二进制数据填充 byte 数组 您可以指定要返回的特定数据缓冲区大小以及从返回的数据中读取的第一个字节的起始位置 GetBytes 将返回 long 值 它表示所返回的字节数 如果向 GetBytes 传递空的 byte 数组 所返回的长值将是 BLOB 中字节的总数 您可以选择将字节数组中的某索引指定为所读取数据的起始位置 以下示例从 Microsoft SQL Server 中的 pubs 示例数据库中返回发行者 ID 和徽标 发行者 ID (pub_id) 是字符字段 而徽标则是图形 即 BLOB 请注意 由于必须按顺序访问字段 所以将在访问徽标之前访问当前数据行的发行者 ID [Visual Basic]Dim pubsConn As SqlConnection = New SqlConnection(Data Source=localhostIntegrated Security=SSPIInitial Catalog=pubs)Dim logoCMD As SqlCommand = New SqlCommand(SELECT pub_id logo FROM pub_info pubsConn)Dim fs As FileStream Writes the BLOB to a file (* bmp) Dim bw As BinaryWriter Streams the binary data to the FileStream object Dim bufferSize As Integer = The size of the BLOB buffer Dim outbyte(bufferSize ) As Byte The BLOB byte() buffer to be filled by GetBytes Dim retval As Long The bytes returned from GetBytes Dim startIndex As Long = The starting position in the BLOB output Dim pub_id As String = The publisher id to use in the file name Open the connection and read data into the DataReader pubsConn Open()Dim myReader As SqlDataReader = logoCMD ExecuteReader(CommandBehavior SequentialAccess)Do While myReader Read() Get the publisher id which must occur before getting the logo pub_id = myReader GetString( ) Create a file to hold the output fs = New FileStream(logo &pub_id &bmp FileMode OpenOrCreate FileAccess Write)bw = New BinaryWriter(fs) Reset the starting byte for a new BLOB startIndex = Read bytes into outbyte() and retain the number of bytes returned retval = myReader GetBytes( startIndex outbyte bufferSize) Continue reading and writing while there are bytes beyond the size of the buffer Do While retval = bufferSizebw Write(outbyte)bw Flush() Reposition the start index to the end of the last buffer and fill the buffer startIndex = startIndex + bufferSizeretval = myReader GetBytes( startIndex outbyte bufferSize)Loop Write the remaining buffer bw Write(outbyte)bw Flush() Close the output file bw Close()fs Close()Loop Close the reader and the connection myReader Close()pubsConn Close()[C#]SqlConnection pubsConn = new SqlConnection(Data Source=localhostIntegrated Security=SSPIInitial Catalog=pubs)SqlCommand logoCMD = new SqlCommand(SELECT pub_id logo FROM pub_info pubsConn)FileStream fs// Writes the BLOB to a file (* bmp) BinaryWriter bw// Streams the BLOB to the FileStream object int bufferSize = // Size of the BLOB buffer byte[] outbyte = new byte[bufferSize]// The BLOB byte[] buffer to be filled by GetBytes long retval// The bytes returned from GetBytes long startIndex = // The starting position in the BLOB output string pub_id = // The publisher id to use in the file name // Open the connection and read data into the DataReader pubsConn Open()SqlDataReader myReader = logoCMD ExecuteReader(CommandBehavior SequentialAccess)while (myReader Read()){// Get the publisher id which must occur before getting the logo pub_id = myReader GetString( )// Create a file to hold the output fs = new FileStream(logo + pub_id + bmp FileMode OpenOrCreate FileAccess Write)bw = new BinaryWriter(fs)// Reset the starting byte for the new BLOB startIndex = // Read the bytes into outbyte[] and retain the number of bytes returned retval = myReader GetBytes( startIndex outbyte bufferSize)// Continue reading and writing while there are bytes beyond the size of the buffer while (retval == bufferSize){bw Write(outbyte)bw Flush()// Reposition the start index to the end of the last buffer and fill the buffer startIndex+= bufferSizeretval = myReader GetBytes( startIndex outbyte bufferSize)}// Write the remaining buffer bw Write(outbyte)bw Flush()// Close the output file bw Close()fs Close()}// Close the reader and the connection myReader Close()pubsConn Close()lishixinzhi/Article/program/net/201311/12026


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/sjk/10067276.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-04
下一篇 2023-05-04

发表评论

登录后才能评论

评论列表(0条)

保存