`
pitt_wang
  • 浏览: 11854 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

oracle9i10编程艺术摘录

阅读更多

并发:

如果只是读数据,Oracle 绝不会对数据锁定。不会因为简单的读操作在数据行上锁定。

写入器(writer)不会阻塞读取器(reader)。换种说法:读(read)不会被写(write)阻塞。

写入器想写某行数据,但另一个写入器已经锁定了这行数据,此时该写入器才会被阻塞。读取器绝对不会阻塞写入器。

多版本:

这正是Oracle 并发控制机制的基础,Oracle 采用了一种多版本、读一致(read-consistent)的并发模型。

读一致查询:对于一个时间点(point in time),查询会产生一致的结果。

非阻塞查询:查询不会被写入器阻塞,但在其他数据库中可能不是这样。

。多版本(multi-versioning)一词实质上指Oracle 能够从数据库同时物化多个版本的数据。

实际上是,DELETE 命令为我们把数据保留下来,把它放在一个称为undo 段(undo segment)的数据区,这个数据区也称为回滚段(rollback segment)。

过去,Oracle 总是基于查询的某个时间点来做决定(从这个时间点开始查询是一致的)。也就是说,

Oracle 会保证打开的结果集肯定是以下两个时间点之一的当前结果集:

游标打开时的时间点。这是READ COMMITTED 隔离模式的默认行为,该模式是默认的事务模式。

查询所属事务开始的时间点。这是READ ONLY SERIALIZABLE 隔离级别中的默认行为。

不过,从Oracle9i 开始,情况要灵活得多。实际上,我们可以指示Oracle 提供任何指定时间的查询

结果(对于回放的时间长度有一些合理的限制;当然,这要由你的DBA 来控制),这里使用了一种称为闪回

查询(flashback query)的特性。

首先得到一个SCN,这是指系统修改号(System Change Number)或系统提交号

System Commit Number);这两个术语可互换使用。SCN Oracle 的内部时钟:每次发生提交时,这个

时钟就会向上滴答(递增)。实际上也可以使用日期或时间戳,不过这里SCN 很容易得到,而且相当准确如果你使用的是Oracle 10g 及以上版本,就有一个“闪回”(flashback)命令,它使用了这种底层

多版本技术,可以把对象返回到以前某个时间点的状态

ALTER TABLE EMP ENABLE ROW MOVEMENT。这个命令的作用是,允许Oracle 修改分配给行的rowid

racle

会利用多版本来得到结果,也就是查询开始时那个时间点的结果,然后完成查询,而不做任何锁定。

,如何保证得到正确的答案同时又不降低并发性?秘密就在于Oracle 使用的事务机制。只要你修

改数据,Oracle 就会创建撤销(undo)条目。这些undo 条目写至undo 段(撤销段,undo segment)。如

果事务失败,需要撤销,Oracle 就会从这个回滚段读取“之前”的映像,并恢复数据。除了使用回滚段数

据撤销事务外,Oracle 还会用它撤销读取块时对块所做的修改,使之恢复到查询开始前的时间点。这样就

能摆脱锁来得到一致、正确的答案,而无需你自己对任何数据锁定。

Oracle 能充分使用不同时间点的数据快照来提供读一致查询和非阻塞查询。

实际上,在Oracle 中这样做是很不好的。在Oracle 中,如果在存储过程中创建表,你

会发现存在以下问题:

DDL 操作会阻碍可扩缩性。

DDL 操作的速度往往不快。

DDL 操作会提交事务。

必须在所有存储过程中使用动态SQL 而不是静态SQL 来访问这个表。

PL/SQL 的动态SQL 没有静态SQL 速度快,或者说没有静态SQL 优化。

 

对于这个问题,正确的解决方法是针对各个数据库使用最合适的代码。在Oracle 中,代码应该如下

(假设表T 需要所生成的主键):

create table t ( pk number primary key, ... );

create sequence t_seq;

create trigger t_trigger before insert on t for each row

begin

select t_seq.nextval into :new.pk from dual;

end;

其效果是为所插入的每一行自动地(而且透明地)指定一个惟一键。还有一种性能更优的方法:

Insert into t ( pk, ... ) values ( t_seq.NEXTVAL, ... );

也就是说,完全没有触发器的开销(这是我的首选方法)

在第一个例子中,我们特意使用了各个数据库的特性来生成一个非阻塞、高度并发的惟一键,而且未

对应用代码带来任何真正的改动,因为在这个例子中所有逻辑都包含在DDL 中。

 

这里有两个选择,一种做法是不使用存储过程返回结果集,另一种做法是针对不同的数据库实现不

同的代码。我就坚持第二种做法,即针对不同的开发商编写不同的代码,而且大量使用存储过程。

 

操作系统相关(operating systemdependent

OSD)代码

内联视图:对“查询”的查询

select p.id, c1_sum1, c2_sum2

from p,

(select id, sum(q1) c1_sum1

from c1

group by id) c1,

(select id, sum(q2) c2_sum2

from c2

group by id) c2

where p.id = c1.id

and p.id = c2.id

标量子查询:每行运行另一个查询

select p.id,

(select sum(q1) from c1 where c1.id = p.id) c1_sum1,

(select sum(q2) from c2 where c2.id = p.id) c2_sum2

from p

where p.name = '1234'

WITH 子查询分解

with c1_vw as

(select id, sum(q1) c1_sum1

from c1

group by id),

c2_vw as

(select id, sum(q2) c2_sum2

from c2

group by id),

c1_c2 as

(select c1.id, c1.c1_sum1, c2.c2_sum2

from c1_vw c1, c2_vw c2

where c1.id = c2.id )

select p.id, c1_sum1, c2_sum2

from p, c1_c2

where p.id = c1_c2.id

 

Oracle 数据库提供了一个称为细粒度访问控制(fine-grained access controlFGAC)的特性。简

而言之,这种技术允许开发人员把过程嵌入数据库中,向数据库提交查询时可以修改查询

 

游标共享可能会改变应用的行为(例如,列宽发生变

化),而且由于它删除了SQL 中的所有直接量,甚至包括那些绝对不会变化的直接量,所以可能会对查询计

划带来负面影响。

 

开发得很好的应用从不需要游标共享。从长远来看,要尽可能地使用绑定变量,而在需要时才使用常量,

这才是正确的做法。

 

数据库(database):物理操作系统文件或磁盘( disk)的集合。

 

实例(instance):一组Oracle 后台进程/线程以及一个共享内存区,这些内存由同一个计

算机上运行的线程/进程所共享。

 

。实例和数据库之间的关系是:数据库可以由多

个实例装载和打开,而实例可以在任何时间点装载和打开一个数据库。实际上,准确地讲,实例在其整个

生存期中最多能装载和打开一个数据库!

 

Oracle

的真正应用集群(Real Application ClustersRAC)是一个例外,这是Oracle 提供的一个选项,允许在

集群环境中的多台计算机上操作,这样就可以有多台实例同时装载并打开一个数据库(位于一组共享物理

磁盘上)。由此,我们可以同时从多台不同的计算机访问这个数据库。Oracle RAC 能支持高度可用的系统,

可用于构建可扩缩性极好的解决方案。

 

Oracle 有一个很大的内存块,称为系统全局区

SGA),在这里它会做以下工作:

维护所有进程需要访问的多种内部数据结构;

缓存磁盘上的数据,另外重做数据写至磁盘之前先在这里缓存;

保存已解析的SQL 计划;

等等。

 

Oracle 服务器处理请求的两种最常见的方式,并分析它们的基本原理,这两种方式分

别是专用服务器(dedicated server)连接和共享服务器(shared server)连接

 

 

2-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 中的请求队列中①。

第一个可用的共享服务器从请求队列中取出这个请求②并处理。共享服务器的处理结束后,再把响应(返

回码、数据等)放到响应队列中③,接下来调度器拿到这个响应④,传回给客户

 

 

TNS 代表透明网络底层(Transparent Network Substrate),这是Oracle 客户中处理远程连接的“基础”

软件,有了它才有可能建立对等通信。TNS 连接串告诉Oracle 软件如何与远程数据库连接。一般地,你的

机器上运行的客户软件会读取一个tnsnames.ora 文件。这是一个纯文本的配置文件,通常放在

[ORACLE_HOME]\network\admin 目录下([ORACLE_HOME] 表示Oracle 安装目录的完整路径)。

 

 

与实例相关的文件只有:

参数文件

跟踪文件

警告文件

 

构成数据库的文件包括:

数据文件

临时文件

控制文件

重做日志文件

密码文件

 

Oracle 10g 开始,又增加了两种新的可选文件类型

修改跟踪文件

闪回日志文件

通常与数据库有关的其他类型的文件

转储文件

数据泵文件

平面文件               

3.1 参数文件

SID 是站点标识符(site identifie

备份和恢复工具——恢复管理器(Recovery ManagerRMAN

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics