北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3,数据库应用程序体系结构
? 数据库系统是指在计算机系统中引入数
据库后的系统,一般由数据库, 数据库管
理系统, 应用系统, DBA,用户组成 。
? 本章介绍数据库应用程序的数据访问与
数据库应用系统的体系结构 。
3.1嵌入式 SQL
3.2事务处理技术
3.3数据库应用系统体系结构
3.4中间件
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1 嵌入式 SQL
? 为什么使用嵌入式 SQL?
—有些数据访问任务对于交互式的非过程的 SQL是 无
法完成的任务 。
—使用交互式 SQL,必须知道表名、列名并且能够写
出符合语法的 SQL语句。
—实际的应用系统是非常复杂的,数据库访问只是其
中一个部件。有些动作如与用户交互、图形化显示
数据等只能用高级语言实现。
? 嵌入到过程性主语言中使用的 SQL称为嵌入式
SQL 。 主 语 言 可 以 是 C 或 Java( 不 一 定 是
Windows环境 ).也可以是 Visual Basic,Delphi
(Windows环境 )等 。
? ORACLE的 Pro*C即是使用嵌入式 SQL的平台 。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1 嵌入式 SQL
? 把 SQL嵌入主语言使用时必须解决的三个问题,
1.区分 SQL语句与主语言语句,用 EXEC SQL开始,
2.数据库工作单元和程序工作单元之间的通信,
SQL语句可以使用主语言的程序变量 (简称主
变量 ),这些变量名前加冒号 (:)作标志,以区别于
字段名。这些变量由 BEGIN DECLARE SECTION与
END DECLARE SECTION语句之间说明,
主语言中不能引用数据库中的字段变量,
SQL语句执行后,系统要反馈给应用程序若干
信息,这些信息送到 SQL的通信区 SQLCA。 SQLCA
用语句 EXEC SQL INCLUDE加以定义。
3.一个 SQL语句原则上可产生或处理一组记录,
而主语言一次只能处理一个记录,为此必须协调
两种处理方式。这是用游标来解决的。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1 嵌入式 SQL
主语言 + 嵌入 SQL
预处理
主语言 + 函数调用
主语言编译器
主语言执行程序
预处理器把嵌入的 SQL语句从主程
序命令中分离出来,转换成相应
的主语言语句, 例,
1.UNIX环境下,程序员创建包含
SQL的 main.pc的源程序,
2.Oracle程序员调用预编译器,
proc iname=main.pc
生成 main.c,其中 SQL语句被纯 c
语句 (Orcale运行期库函数 )替换,
3.主语言编译
cc -c main.c,生成 main.o目标文件,
4,连编生成可执行文件,
? 嵌入式 SQL的执行
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.1 C语言中嵌入式 SQL
#include <stdio.h>
#include ―prompt.h‖
exec sql include sqlca; /*声明通讯区 */
char cid_prompt[]=―请输入顾客号,‖;
int main( )
{
exec sql begin declare section;
char cust_id[5],cust_name[14];
float cust_discnt;
char user_name[20],user_ped[20];
exec sql end declare section;
/*声明变量 */
exec sql whenever sqlerror goto report_error;
exec sql whenever not found goto notfound;
/*出错处理 */
strcpy(user_name,‖mytest‖);
strcpy(user_pwd,‖test‖);
exec sql connect,user_name
identified by,user_pwd; /*连接 */
while((prompt(cid_prompt,1,cust_id,4))>=0)
{
exec sql select cname,discnt
into,cust_name,:cust_discnt
from customers where cid=:cust_id;
exec sql commit work;
printf(―顾客名, %s 折扣率, %5.1f\n‖,
cust_name,cust_discnt);
continue;
notfound,printf(―没找到 %s,继续 \n‖,cust_id);
} /*根据输入的顾客 ID查询顾客信息 */
exec sql commit release; /*正常释放连接 */
return 0;
report_error:
print_dberror(); /*出错信息 */
exec sql rollback release; /*释放连接 */
return 1;
}
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.1 C语言中嵌入式 SQL
? 区分 SQL语句与 C语言语句
嵌入的 SQL语句以 EXEC SQL开始,以分号 (;)结束。
例,exec sql select came,discnt
into,cust_name,:cust_discnt
from customers where cid=:cust_id;
? 嵌入 SQL语句与 C语言之间的数据传递
宿主变量 (宿主变量出现于 SQL语句中时,前面加 (,)
以区别列名 )
C变量既可以用在 C语句中,也可用在 SQL语句中,
用来在两者之间传递数据。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.1 C语言中嵌入式 SQL
? 宿主变量的声明
在嵌入式 SQL语句中使用宿主变量,必须先声明它们:
声明为通常的 C变量,并将其放在下列标识语句之间,
EXEC SQL BEGIN DECLARE SECTION
EXEC SQL END DECLARE SECTION
例, exec sql begin declare section;
char cust_id[5]=‘c001’;
char cust_name[14];
float cust_discnt;
exec sql end declare section;
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.1 C语言中嵌入式 SQL
? 在 SQL中建立连接和释放连接
在一个嵌入式 SQL程序开始,程序面临着和交互式用户
同样的问题:怎样与数据库建立连接,
例, exec sql begin declare section; /*声明变量 */
char user_name[10],user_ped[10];
exec sql end declare section;
strcpy(user_name,’mytest’); /*变量赋值 */
strcpy(user_pwd,’test’);
exec sql connect,user_name
identified by,user_pwd; /*Oracle连接 */
例,exec sql commit release;/*Oracle断开连接 */
exec sql rollback release;/*Oracle断开连接 */
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.2 游标
? SQL与主语言之间操作方式的协调
SQL:一次一集合。
C语言:一次一记录。
– 游标:在查询结果的记录集合中移动的指针。
若一个 SQL语句返回单个元组,则不用游标。
若一个 SQL语句返回多个元组,则使用游标。
– 不需要游标的数据操作
? 结果是一个元组的 select语句
exec sql select came,discnt
into,cust_name,:cust_discnt
from customers where cid=:cust_id;
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.2 游标
– 需要游标的数据操作
当 select语句的结果中包含多个元组时,使用游标可
以逐个存取这些元组。
活动集,select语句返回的元组的集合。
当前行,活动集中当前处理的那一行。游标即是指
向当前行的指针。
游标分类:
? 滚动游标:游标的位置可以来回移动,可在活动
集中取任意元组。
? 非滚动游标:只能在活动集中顺序地取下一个元
组。
? 更新游标:数据库对游标指向的当前行加锁,当
程序读下一行数据时,本行数据解锁,下一行数
据加锁。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.2 游标
? 定义一个游标,使之对应一个 select语句
DECLARE 游标名 [SCROLL] CURSOR
FOR select语句 [for update [of列表名 ]]
for update任选项,表示该游标可用于对当前行
的修改与删除。
? 打开一个游标,执行游标对应的查询,结果集
合为该游标的活动集。
OPEN 游标名
在游标被声明之后,它仍然不是活动状态,在程序开始检
索信息之前,执行 SQL的 OPEN语句打开这个游标,游标
被打开之后,可使用取( fetch)操作从游标中每次检索
一行,程序完成检索后,应关闭游标.
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.2 游标
? 在活动集中将游标移到特定的行,并取出该行
数据放到相应的宿主变量中。
FETCH [NEXT | PRIOR | FIRST | LAST |
CURRENT | RELETIVE n | ABSOLUTE n]
游标名 INTO [宿主变量表 ]
? 关闭游标,释放活动集及其所占资源。需要再
使用该游标时,执行 open语句。
CLOSE 游标名
? 删除游标,以后便不能再对该游标执行 open语
句了,
FREE 游标名
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.2 游标
#define ture 1
#include <stdio.h>
#include ―prompt.h‖
exec sql include sqlca; /*声明通讯区 */
int main( )
{
char cid_prompt[]=―请输入顾客号,‖;
exec sql begin declare section;
char cust_id[5],agent_id[4];
double dollar_sum;
char user_name[20],user_ped[20];
exec sql end declare section; /*声明变量 */
exec sql declare agent_dollars cursor for
select aid,sum(dollars) from orders
where cid=:cust_id group by aid;/*游标 */
exec sql whenever sqlerror goto report_error;
exec sql whenever not found goto finish;
/*出错处理 */
strcpy(user_name,‖mytest‖);
strcpy(user_pwd,‖test‖);
exec sql connect,user_name
identified by,user_pwd; /*连接 */
while((prompt(cid_prompt,1,cust_id,4))>=0){
exec sql open agent_dollars;
while (ture) {
exec sql fetch agent_dillars into
:agent_id,:dollar_sum; /*游标取值 */
printf(― %s %11.2f\n‖,
agent_id,dollar_sum);
}
continue;
finish,exec sql close agent_dollars;
exec sql commit work; /*游标关闭 */
} /*输入顾客 ID的代理商和金额 */
exec sql commit release; /*正常释放连接 */
return 0;
report_error:
print_dberror(); /*出错信息 */
exec sql rollback release; /*释放连接 */
return 1;
}
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.3 通讯区
? SQL语句执行信息反馈
– 良好的应用程序必须提供对错误的处理,应
用程序需要知道 SQL语句是否正确执行了,
发生错误时的错误代码,执行时遇到特殊情
况时的警告信息。
– SQL通讯区 SQLCA是一个已被声明过的内存结
构,每一嵌入 SQL语句的执行情况在其执行完
成后写入 USERCA结构中的各变量中,根据
SQLCA中的内容可以获得每一嵌入 SQL语句执
行后的信息,应用程序就可以做相应的处理。
– 为了说明 (USERCA),必须在应用程序中包括,
EXEC SQL INCLUDE SQLCA;
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.3 通讯区
? SQLCODE,SQLCODE是 SQLCA的结构一个成员。
它是一个每次执行完 SQL语句都被更新的整型
变量。
– 如果执行成功,SQLCODE为 0;
– 如果语句没有产生错误,但遇到了没有数据,
SQLCODE为 100;
– 除去成功返回 0或没有数据返回 100的情况,其他都
是某种错误并返回一个负数。
? SQL-99和 X/OpenSQL等标准提倡用 SQLSTATE取
代 SQLCODE检测 SQL的执行情况,并将 SQLSTATE
设置为标准,但在产品中还不一定支持。例如
ORACLE中,预处理程序运行时必须设置
MODE=ANSI才能支持 SQLSTATE.
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.3 通讯区
? SQLSTATE,SQLSTATE作用与 SQLCODE作用相
同,但它是在标准方式下起作用。 SQLCODE是
一个整数,SQLSTATE是一个长度为 5的只能由 A
到 Z字符和 0到 9数字组成的字符串。 5个字符分
为两组,前两个为类码,后三个为子类码。
SQL标准规定:分类码的第一个字符可为 A到 H
或 0到 4,这样分类主要为了统一,第一个字符
为 I到 Z或 5到 9的分类码留给软件开发者去定义。
分类码 00指成功,01指成功但产生一个警告,02指没
有数据,等价于 SQLCODE的 100,非 00,01和 02指语句没
有成功完成。可以查阅数据库系统产品的嵌入式 SQL参
考指南得到 SQLSTATE,SQLCODE,SQLCA,确定主要的
出错条件,以它们的报告方式。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.4 错误处理
? Whenever语句使我们在遇到出错和其他情况时,
控制程序的运行,
EXEC SQL WHENEVER 条件 动作
条件可以是
– SQLERROR:执行错误,如连接不成功等;
– NOT FOUND:没有数据,如游标指针到头或到尾等;
– SQLWARNING:警告错误。
动作可以是
– CONTINUE:继续正常流程;
– GOTO 标号:转移到标号行继续执行;
– STOP:结束程序,撤消当前事务,并断开数据库连接;
– DO 函数:引发一个对已经命名的函数的调用。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.4 错误处理
? 没有 WHENEVER语句时缺省动作是 Continue.
? 如果 SQLCODE为负,则 SQLERROR为真,如果
SQLCODE为 100或 SQLSTATE为 02000,则 NOT
FOUND为真。抽取错误信息的确切代码依赖
于所使用的数据库系统。
? WHENEVER语句的主要价值在于减少处理错
误的代码行数,另外 WHENEVER的语法可以
在不同数据库系统之间进行最大限度的移植。
例如利用检测条件 NOT FOUND在不同数据库
产品中可能有不同的 sqlca.sqlcode值,但 NOT
FOUND却始终表示没有发现记录这一错误。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.5 指示变量
? 如果一个宿主变量所对应的数据库字段允许空
值,或字符串类型的宿主变量的长度可能小于
所对应的数据库字段的长度,则需要一个指示
变量来指明数据库访问的返回状态。
? 指示变量, 是一个 C变量,用来指示返回给宿
主变量的值是否为 null值,以及返回给宿主变
量的字符串是否发生了截断。
指示变量的返回值:
= 0:取到主变量的值不空,没有发生截断。
= ?1:取到主变量的值为空值。
> 0:取到主变量的值发生了截断,指示变
量的值是截断前的字符串的实际长度。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.5 指示变量
? 指示变量的用法:声明与宿主变量的声明方式
一样,在数据操纵语句中,在宿主变量和指示变
量之间加 (, )或关键字 indicator。
例,exec sql begin declare section
float cust_discnt;
short int cd_ind;
exec sql end declare section
exec sql select discnt into,cust_discnt
[indicator]:cd_ind
from customers where cid=:cust_id;
在检索之后,如果 cd_ind的值为 -1,则变量
cust_discnt得到了一个空值;如果为 0,则
cust_discnt中的值是正常的。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.5 指示变量
? 不管读取数据还是更新数据,都可以用指示变
量的值 -1代表空值。
例,要将表 customers的某一行的 discnt值设置为空
值,可以这样写:
cd_ind=-1
exec sql update customers
set discnt=:cust_discnt
indicator,cd_ind
where cid=:cust_id;
? 实际上还可以进一步扩展指示变量的值,例如
DB2 UDB的产品中,如果指示变量的值为 -2,
意味着是由于一个错误而不是数据库中存储的
值而使检索到的值为空值。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.1.6 嵌入式 SQL语句
? 检索,EXEC SQL SELECT [ALL|DISTINCT] 表达式
INTO 宿主变量 FROM 表名 WHERE 条件 ;
? 游标定义,EXEC SQL DECLEARE 游标名 CURSOR
FOR 子查询 [ORDER BY…] [FOR READ ONLY
|UPDATE [OF 列名 ]];
? 游标打开与关闭,EXEC SQL OPEN|CLOSE 游标名 ;
? 游标取值,EXEC SQL FETCH
[NEXT|PRIOR|FIRST|LAST |CURRENT|RELETIVE
n|ABSOLUTE n] 游标名 INTO 宿主变量 ;
? 删除,EXEC SQL DELETE FROM 表名 [WHERE条件
|WHERE CURRENT OF 游标名 ];
? 修改,EXEC SQL UPDATE 表名 SET 列 =表达式
[WHERE 条件 |WHERE CURRENT OF 游标名 ];
? 增加,EXEC SQL INSERT INTO 表名 [(列名 )]
VALUES(表达式 );
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2 事务处理技术
? 保证数据的一致性和数据库的并行性,是衡量一
个数据库的最基本和最重要的指标之一。
一致性,以一致性规则为基础的数据逻辑关系。
如转帐任务不能造成帐户金额的不平衡。
并行性,各个用户能够实现对数据库资源的共享。
数据并发是多用户系统的基本要求,数据一致是
因为有数据并发存在,为了适应多用户系统,协
调管理数据库中的数据,保证各个用户的任务能
够顺利准确地完成。
事务处理 是实现数据库一致性和并行性的重要手
段。 在保证一致性的前提下最大限度地提高并发
度。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2 事务处理技术
? 数据操纵以 SQL为基础,但单条 SQL语句不一定
能完成所有的用户请求,许多用户请求需要若
干条 SQL语句,而且这些语句有关联,要么全
做,要么全不做。
? 如果许多用户的众多 SQL语句不加控制,随意
执行,必然破坏数据的一致完整,出现丢失修
改、不可重复读、读脏数据的错误。
? 数据库系统要对用户的操作进行控制 (事务控
制和封锁技术 ),保证并发的同时保证数据的
一致。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.1 事务概念
? 事 务是由一系列操作序列构成的程序执行单元,
这些操作要么都做,要么都不做,是一个不可
分割的工作单位。
事务是数据库提供的一种手段,应用程序员将
一系列操作组合在一起作为一个整体以便数据
库系统提供保证。事务才是对数据库系统进行
操作的最小合法单位。 DBMS在事务级而不是
在语句级确保数据的一致性。
? 事务以 Begin transaction开始,以 Commit work
或 Rollback work结束。
嵌入式 SQL,EXEC SQL COMMIT WORK;
EXEC SQL ROLLBACK WORK;
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.1 事务概念
? Commit work表示提交,事务正常结束。
Rollback work表示事务非正常结束,撤消事务
已做的操作,回滚到事务开始时状态。
事务的内容只限于数据更新操作 (增删改 ),不包
含其他 SQL命令。
在标准 SQL中,没有 Begin transaction语句,上
一条 Commit或 Rollback或 SQL修改命令即为事
务的开始。
有的 DBMS使用 Begin transaction作为事务的开
始。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.1 事务概念
? 事务特性 (ACID)
– 原子性 (Atomicity)
事务的更新操作必须作为一个整体,其中包
含的所有操作要么全做,要么全不做。
原子性由系统 恢复机制 实现。
– 一致性 (Consistency)
事务的成功完成将数据库从一个一致状态转
变到另一个一致状态。
事务开始前,数据库处于一致性的状态;事
务结束后,数据库必须仍处于一致性状态。
数据库的一致性状态由 用户 来负责。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.1 事务概念
? 事务特性 (ACID)
– 隔离性 (Isolation)
系统必须保证事务不受其它并发执行事务的影响。
对任何一对事务 T1,T2,在 T1看来,T2要么在 T1开
始之前已经结束,要么在 T1完成之后再开始执行。
隔离性通过 并发控制机制 实现。
– 持久性 (Durability)
一个事务一旦提交之后,它对数据库的影响必须是
永久的,无论发生何种系统故障。
持久性通过 恢复机制 实现。
事务的原子性、隔离性、持久性由数据库系统加以保
证,一致性一般由程序员在编写程序中予以保证 。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.2 事务的调度
? 事务的调度,DBMS在处理用户提交事务时的
策略,即事务调度。事务的执行顺序称为一个
调度,表示事务的指令在系统中执行的时间顺
序。
– 一组事务的调度必须保证
? 包含了所有事务的操作指令
? 一个事务中指令的顺序必须保持不变。
– 串行调度
? 在串行调度中,属于同一事务的指令紧挨在一起。
? 对于有 n个事务的事务组,可以有 n!个有效调度。
– 并行调度
? 在并行调度中,来自不同事务的指令可以交叉执行。
? 当并行调度等价于某个串行调度时,则称它是正确的 。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.2 事务的调度
? ANSI SQL-99标准中,一致性级别 (隔离级别 )的定义
– serializable:一个调度的执行必须等价于一个串行
调度的结果。
– repeatable read:只允许读取已提交的记录,并要求
一个事务对同一记录的两次读取之间,其它事务不
能对该记录进行更新。
– read committed:只允许读取已提交的记录,但不要
求可重复读。
– read uncommitted:允许读取未提交的记录。
? 在 SQL-99的语法中允许在启动事务的 SQL语句之前设
置隔离级别。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.3 事务的数据封锁
? 数据库管理系统采用 数据封锁技术 和事务技术
解决并发性和一致性问题,数据封锁有两种封锁
模式,
专用锁,当一个事务以专用方式封锁某个资源时,
只有此事务可以改变其中的内容,在该事务结束
或释放其资源后,其它事务才能使用 ;
共享锁,允许已封锁的资源被其它事务适度共享,
多个事务可以在同一资源上申请共享锁,
? 根据封锁的类型、持锁时间、何时释放的规则,
将封锁协议分为一级封锁协议、二级封锁协议、
三级封锁协议。 不同封锁协议在不同程度上保
证数据一致性和系统并发性 。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.3 事务的数据封锁
? 在 SQL语句执行时,所有必要的 封锁均由 DBMS自
动完成 (也可显式加锁 ),事务中所有为执行 SQL语
句建立的封锁均要延续到事务结束时才能释放,
否则一个数据库对象在同一时间段内被多个事务
交替操作,可能造成对数据库数据的破坏,
? 当参与封锁的事务较多,而每个事务封锁的资源
也较多时,可能出现‘死锁’情况。
? 预防死锁的方法有一次封锁法、顺序封锁法。
? 死锁的诊断有超时法、有向图法。死锁发生后,
DBMS通常选择一个处理死锁代价最小的事务将
其撤消,并恢复该事务。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.3 事务的数据封锁
? 两段锁协议 (Two-phase Locking)
– 内容:
①在对任何数据进行读写之前,事务首先要获
得对该数据的封锁。
②在释放一个封锁之后,事务不再获得任何其
它封锁。
即事务分为两个阶段:
生长阶段:获得封锁。
收缩阶段:释放封锁。
– 定理:若所有事务均遵从两段锁协议,则这些
事务的所有并行调度都是可串行化的。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.4 ORACLE事务控制 -回退段
? ORACLE为了适应事务控制设置了 回退段 这一
数据库对象,系统利用回退段来确保诸如读一
致性、数据库恢复等管理功能。
? ORACLE在缺省情况下,读数据不加锁,通过回
退段 (Rollback Segment)保证用户不读脏数据和
可重复读,
? 表空间中的数据按段来组织,数据段、索引段、
暂存段和回退段,回退段是一块磁盘存储区域,
回退段可以由用户创建,但只能由系统进程使
用。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.4 ORACLE事务控制 -回退段
? 回退段中的数据是为事务服务的,每执行事
务时,系统先在指定回退段上记录将要对数
据进行的更改,以事务为单位,各个事务的
回退信息链接在一起。
? 当事务要回退时,利用回退信息将数据块中
的数据恢复到先前的状态。
? 事务成功提交后,回退信息逐渐失效 (在提交
之前申请的查询需要这些信息保证 读一致性,
事务提交前对数据的变动不会为其他用户所
知晓 )。回退段可以循环使用。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.4 ORACLE事务控制 -回退段
? 用回退段保证读一致性 (不读脏数据和可重复读 ):
1 2 3 4 5 6
Tu2
Tu1
Ts3
Ts2
Ts1
时间
事务
表 customers
时间 回退信息
3 discnt=10
5 discnt=11
数据缓冲区
cid discnt
c001 10
11
15
数据段, 回退段,
Tu1
Tu2
例, 有 5个事务并发,
Ts1,Ts2,Ts3为查询事务,
Tu1,Tu2为更新事务,
Tu1:UPDATE customers
SET discnt=discnt*1.1
WHERE cid=?c001‘;
Tu2,UPDATE customers
SET discnt=15 WHERE
cid=?c001‘;
事务开始和完成时间段
如右上图,
事务对回退段影响如右
下图,
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.4 ORACLE事务控制 -回退段
? 用回退段保证读一致性 (不读脏数据和可重复读 ):
事务的开始顺序和基准时间为,Ts1=0 – Tu1=3 – Ts2=4 –
Tu2=5 – Ts3=6;
事务的完成顺序和基准时间为,Tu1=4 – Tu2=6 – Ts1>6 –
Ts2>6 – Ts3>6;
数据缓冲区的内容是最新更改的结果,回退段按时间顺
序记录了每次更改以前的数据 ;
尽管 Tu1和 Tu2两次更改了 discnt的值,但 Tu1开始之前
Ts1已开始,所以在时间 4结束的 Tu1回退信息并不马上消
失,保证 Ts1从回退段中查得 discnt为 10,Tu2开始之前 Ts2已
开始,所以在时间 6结束的 Tu2回退信息并不马上消失,保证
Ts2从回退段中查得 discnt为 11,Ts3基准时间是 6,从缓冲区
中查得 discnt为 15.
Ts1和 Ts2结束后才清除回退段信息,
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.4 ORACLE事务控制 -回退段
? 在数据库创建时 SYSTEM表空间中建立了
SYSTEM回退段。每个数据库可以有一个或多
个回退段,最好只将 SYSTEM回退段用于系统
事务,将用户事务分配在其他回退段上,以提
高资源利用率。
? 创建 回退段时可同时设定其存储参数,回退段
至少要包括两个区间 (MINEXTENTS),回退段
的区间总数受到回退段存储参数 MAXEXTENTS
的限制。
? 一个事务的回退信息按顺序在指定的回退段中
写入。创建多少个回退段及给每个回退段分配
多少区间,要考虑可能出现的最大并发事务数,
每个回退段所能同时服务的事务数。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.4 ORACLE事务控制 -回退段
? 事务的执行过程(采用日志和回退段双重记录
事务活动):
进入回退段,写入回退信息
从数据段读入缓冲区,SQL处理
记载日志文件
提交,写更改结果到磁盘 回退,写回退信息到磁盘
事务第一条更新语句
事务结束N
Y
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.5 ORACLE事务控制 -语句
? ORACLE事务控制语句,
– COMMIT [WORK];
清除本事务的全部保留点,清除为执行事务建立的封
锁机制,结束本事务,提交数据,
– SAVEPOINT 保留点名 ;
保留点是一事务范围内的中间标志,经常用于将长事
务划分为短小的部分,保留点可标志在长事务的任何
点,允许回退该点之后的工作,保留点主要作为一种调
试手段使用,在一个事务中如果用相同的保留点名创
建第二个保留点,则前一个保留点被删除掉,每个事务
最大的活动保留点由初始化参数文件中的参数
SAVEPOINTS设定,极限值为 255,
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.5 ORACLE事务控制 -语句
– ROLLBACK [WORK] [TO [SAVEPOINT] 保留点
名 ];
清除本事务的全部保留点,清除为执行事务建立的
封锁机制,结束本事务,回退数据,
数据定义语句 CREATE,DROP总引发提交,系统
正常关闭时,未提交事务将隐式提交,一个进程或
例程非正常终止,未提交事务将隐式回退。
– SET TRANSACTION [READ ONLY] [READ
WRITE] [USE ROLLBACK SEGMENT 回退段名 ];
设置事务是对事务的一种控制,建立当前事务为
只读事务或读写事务,控制事务使用指定的回退段
空间。只读事务不生成回退信息,所以不必分配回
退段,缺省状态下事务为读写事务。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.6 ORACLE事务控制 -数据锁
? ORACLE提供了各种类型的封锁机制保证并发操
作时数据的一致,对数据库对象的封锁由系统自
动完成。数据库应用设计者可以干预自动封锁过
程以提高整体效率,
? ORACLE主要封锁类型有,
– 数据锁, 目的是保护数据,用于封锁表和表中的某些行 ;
– 字典锁, 目的是保护数据库对象的结构,用于表对象的
定义 ;
– 内部锁, 用于保护数据库的内部结构,如文件等,
? 数据锁有两种级别的封锁方式,
– 表封锁,封锁表中的所有行,数据并行度低,
– 行封锁,行级封锁在对应表上加字典锁,
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.6 ORACLE事务控制 -数据锁
? ORACLE表上的数据锁类型有,
– RS:行共享,用于让事务封锁表中的部分行,以便于数
据修改,但在建立封锁时并不立即修改数据,当事务在
一表持有行共享锁时,允许其他事务并行查询、插入、
修改、删除。
– RX:行专有,事务可对表中部分行建立专有锁,使事务
可以在以后的操作中多次修改这些行。具有行专有
锁的表允许其他事务并行查询、插入、修改、删除。
– S:共享,共享锁将阻止其他事务修改表中的内容,具
有共享锁的表拒绝其他事务插入、修改、删除。
– SRX:共享行专有,每个表上的共享行专有锁只能由一
个事务建立,有这种类型锁的表只能允许其他事务
查询。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.6 ORACLE事务控制 -数据锁
– X:专有,事务在表上建立专有锁之后,可以独占此表
进行写入操作。
? ORACLE中的 SELECT不用任何数据锁阻塞其
他操作,也称无阻塞查询 。 INSERT、
UPDATE,DELETE引发数据封锁,事务所申
请的全部数据锁在事务提交或回退时一起释放,
表上的数据锁也可以通过显式语句完成 (如下页
表 )。
? 表上的数据锁在事务执行过程中可能发生变化,
如事务为执行带 UPDATE子句的 SELECT语句,
需在选中行上建立行共享锁,如果稍后事务决
定修改其中的某些行,则这些行上的行共享锁
将自动转换为行专有锁。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.6 ORACLE事务控制 -数据锁
SQL语句 封锁 允许模式 RS RX S SRX X
Select 无 Y Y Y Y Y
Insert RX Y Y N N N
Delete RX Y Y N N N
Update RX Y Y N N N
Select for update of RS Y Y Y Y N
Lock table in row share mode RS Y Y Y Y N
Lock table in row exclusive
mode
RX Y Y N N N
Lock table in share mode S Y N Y N N
Lock table in share row
exclusive mode
SR
X
Y N N N N
Lock table in exclusive mode X N N N N N
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
3.2.6 ORACLE事务控制 -数据锁
? 数据库设计者应该利用各种方法减少数据对象
的封锁时间,以提高系统并发能力,
在事务中尽可能晚地发出封锁申请;
在备份的数据库对象上操作以减少封锁时间;
利用索引减少封锁时间,查询操作可以根本不
访问索引关联的表,而直接给出查询结果。
? 数据库设计者应该按照约定顺序封锁表减少出
现死锁的可能性,以提高系统并发能力 。
北京邮电大学软件学院 郭文明 2003.06
,数据库设计与开发, 讲义
作业:
1.解释游标,
2.针对 CAP数据库,编写一应用程序,给出任
一产品的 pid,列出购买该产品的前 5名顾客
(cid,cname)及其购买数量,即这些顾客购买
该产品的数量最大,
3.说明数据库管理系统保证数据一致性和并
发性的机制,
4.ORACLE为什么设置回退段?
5.数据库设计者在保证数据一致性和并发性
方面可以有哪些措施?