登陆注册
31848700000022

第22章 数据库的保护(6)

8.2.2.4 Oracle的恢复方法

与备份方法对应的恢复方法也可以分为物理恢复与逻辑恢复。物理恢复是针对物理文件的恢复,逻辑恢复是用Oracle系统提供的IMPORT工具将EXPORT工具存储在一个专门的操作系统文件中的内容按逻辑单元(表、用户、表空间、数据库)进行恢复。IMPORT工具和EXPORT工具必须配套使用。

1.物理恢复

物理恢复又可分数据库运行在非归档方式下脱机恢复、数据库运行在归档方式下的联机恢复。

(1)非归档模式下的物理恢复

非归档方式下脱机恢复是指一旦组成数据库的物理文件中有一个文件遭到破坏,必须在数据库关闭的情况下将全部物理文件装入到对应的位置上,进行恢复。上次备份后所做的所有操作都丢失,这些操作必须用手工方法进行恢复。这种恢复方法适合数据库运行于非归档模式,只能恢复到最后一次备份点,并且要求DBA勤做备份,否则损失很严重。

假如组成数据库物理文件中的任何一个文件遭到破坏,在非归档模式下只能按下列方法进行整个数据库的恢复,恢复到上次备份点,上次备份后所做的所有操作必须手工重做。

首先保证数据库运行在非归档模式,接着关闭数据库,然后将非归档模式下物理冷备份时备份出来的所有数据文件、联机日志文件、控制文件按备份时的路径分别装入到数据库,最后重新启动数据库。

下列示例说明了非归档模式下物理恢复的步骤,并说明了备份后所做的操作没有恢复。

打开数据库:

SQL>connect/as sysdba

SQL>startup

在USERS表空间上建立test表,并往test表中插入数据。例如,连接到scott用户,在scott用户中建立test表,并往test表中插入数据。

SQL>connect scott/tiger

SQL>CREATE TABLE test(t1 number,t2 date)TABLESPACE users

SQL>INSERT INTO test VALUES(1,sysdate)

SQL>INSERT INTO test VALUES(2,sysdate)

SQL>INSERT INTO test VALUES(3,sysdate)

SQL>COMMIT

关闭数据库:

SQL>connect/as sysdba

SQL>shutdown

数据库已经关闭。

已经卸载数据库。

Oracle 例程已经关闭。

SQL>EXIT

用操作系统命令删除users01.dbf文件(即删除users表空间所对应的数据文件):

C:\del e:\oracle\oradata\oracle\users01.dbf

启动数据库,观察提示信息:

SQL>connect/as sysdba

SQL>startup

Oracle 例程已经启动。

Total System Global Area 135338868 bytes

Fixed Size 453492 bytes

Variable Size 109051904 bytes

Database Buffers 25165824 bytes

Redo Buffers 667648 bytes

数据库装载完毕。

ORA-01157:不能识别/锁住数据文件9——查看DBWR跟踪文件

ORA-01110:数据文件9:′e:\oracle\oradata\oracle\users01.dbf′

上述提示信息说明没法打开数据库,因为数据文件9找不到。

进行恢复。首先将刚才没有打开的数据库关闭。

SQL>connect/as sysdba

SQL>shutdown

数据库没有打开。

已经卸载数据库。

Oracle 例程已经关闭。

SQL>EXIT

然后用操作系统命令,将8.2.2.3节非归档模式下物理备份中备份出来的整个数据库的所有数据文件、联机日志文件、控制文件按原来的目录路径装入。此时将该目录中的文件全部覆盖。

C:\copy h:\oracle\cold\*.*e:\oracle\oradata\oracle\/*装入整个数据库*/

装入后重新打开数据库。此时所有数据文件、联机日志文件、控制文件都恢复到备份时的状态。

SQL>connect/as sysdba

SQL>startup

Oracle 例程已经启动。

Total System Global Area 135338868 bytes

Fixed Size 453492 bytes

Variable Size 109051904 bytes

Database Buffers 25165824 bytes

Redo Buffers 667648 bytes

数据库装载完毕。

数据库已经打开。

在做了非归档模式下物理冷备份后,测试新建的表test及往表中插入的数据在非归档模式下的物理恢复后是否存在。

SQL>connect scott/tiger

SQL>SELECT*FROM test

SELECT*FROM test

*

error 位于第1 行:

ORA-00942:表或视图不存在

上述测试说明在非归档模式下物理冷备份后,新建的表TEST及往表中插入的数据在非归档模式下物理恢复后不存在。即说明数据库运行于非归档模式时只能恢复到最后一次备份点,备份后所做的操作不能恢复。

(2)归档模式的物理恢复

归档方式下的联机恢复是指一旦这些数据文件中某一个遭到破坏,将该数据文件的备份装入到对应位置,然后利用上次备份后产生的归档日志文件和联机日志文件进行恢复,可以恢复到失败这一刻。这种恢复方法要求数据库必须运行在归档模式。

要求数据库运行在归档模式,并已成功地进行了8.2.2.3节讲述的归档模式下物理备份。如果数据库没有运行在归档模式,按8.2.2.2节讲述的方法将数据库置于归档模式。按下列方法进行归档模式下的物理恢复。

首先打开数据库,并确认数据库运行于归档模式,然后对数据库进行操作,接着将刚在操作的内容归档到归档文件。此时如果组成数据库的物理文件中某一个数据文件遭到破坏,造成数据库无法启动。需要将被破坏的数据文件以前的备份按原路径装入,但因为此数据文件是以前备份的,其序列号与其他没有被破坏的数据文件的序列号不一致,所以必须利用归档的日志文件进行恢复。此时启动数据库到MOUNT状态,发RECOVER命令,系统自动利用备份后产生的归档日志文件进行恢复,恢复到所有数据文件序列号一致时为止。最后将此数据文件设为ONLINE,并打开数据库到OPEN状态。

下列实例说明了归档模式下物理恢复的步骤,并说明恢复了备份后所做的操作。

启动数据库并确认数据库运行在自动归档模式:

SQL>connect/as sysdba

SQL>startup/*启动数据库并保证运行于归档模式*/

SQL>arhive log list/*验证数据库运行于归档模式*/

数据库日志模式 存档模式

自动存档 启用

存档终点E:\oracle\ora92\RDBMS

最早的概要日志序列58

当前日志序列60

建立新用户test并授权,在test用户中建立test表,并往表中插入数据和提交:

SQL>CREATE USER test IDENTIFIED BY test/*建立新用户*/

DEFAULT TABLESPACE users

TEMPORARY TABLESPACE temp

QUOTA 10m ON USERS

SQL>GRANT CONNECT to test/*给用户授权*/

SQL>CONNECT test/test/*新用户连接*/

SQL>CREATE TABLE test(t1 number,t2 date)/*建表*/

SQL>INSERT INTO test values(1,sysdate)/*往表中插入数据*/

SQL>INSERT INTO test values(2,sysdate)

SQL>INSERT INTO test values(3,sysdate)

SQL>COMMIT

SQL>DISCONNECT

以sysdba权限登录,进行日志切换,以便将刚在所做的操作归档到归档日志文件:

SQL>connect/as sysdba

SQL>ALTER SYSTEM SWITCH LOGFILE/*产生日志切换*/

SQL>ALTER SYSTEM SWITCH LOGFILE

SQL>ALTER SYSTEM SWITCH LOGFILE

假设数据库有三个联机日志文件组,日志切换三次,保证刚在插入的数据已被归档到归档日志文件。

关闭数据库,删除数据文件users01.dbf:

SQL>connect/as sysdba

SQL>shutdown

数据库没有打开。

已经卸载数据库。

Oracle 例程已经关闭。

SQL>host del e:\oracle\oradata\oracle\users01.dbf

执行打开数据库命令,观察现象(数据库无法启动,注意提示信息):

SQL>connect/as sysdba

SQL>startup

Oracle 例程已经启动。

Total System Global Area 135338868 bytes

Fixed Size 453492 bytes

Variable Size 109051904 bytes

Database Buffers 25165824 bytes

Redo Buffers 667648 bytes

数据库装载完毕。

ORA-01157:不能识别/锁住数据文件9——查看DBWR跟踪文件

ORA-01110:数据文件9:′e:\oracle\oradata\oracle\users01.dbf′

上述提示信息说明没法打开数据库,因为数据文件9找不到。

将8.2.2.3节归档模式下物理备份的users01.dbf 文件装入到对应的目录:

SQL>host copy h:\oracle\hot\users01.dbf E:\oracle\oradata\oracle\

执行数据库恢复,并打开数据库:

SQL>RECOVER DATABASE AUTO

介质恢复完成。

由于在8.2.2.3节归档模式下物理备份中备份的users01.dbf文件的序列号与其他数据文件和控制文件的序列号不同,所以系统自动使用备份后产生的归档日志文件执行数据库恢复。恢复完成后所有文件的序列号相同。此时将users01.dbf文件置为online状态,以便执行下一步的查询操作;然后将数据库打开。

SQL>ALTER DATABASE DATAFILE′E:\Oracle\ORADATA\Oracle\users01.dbf′ONLINE

SQL>ALTER DATABASE OPEN

数据库已经打开。

上述测试说明在归档模式下物理备份后,新建的表TEST及往表中插入的数据在归档模式下物理恢复后是存在的。即说明数据库运行于归档模式时可以恢复到最后失败点,备份后所做的操作可以通过归档日志文件进行恢复。

2.逻辑恢复

IMPORT工具从EXPORT工具卸出的专门操作系统文件中读取数据,将其插入到数据库中。根据卸出的四种模式(整个数据库模式、用户模式、表模式和表空间模式)可以分别装入整个数据库对象、某一用户的对象、某一张表上的对象或表空间上的对象。拥有IMPFULLDATABASE角色权限的用户才能执行整个数据库的装入。通过在操作系统提示符下运行IMP HELPY命令可以获得IMPORT工具的联机帮助。

装入运行方式有三种:交互方式、命令行方式和参数文件方式。

(1)交互方式

交互方式装入时首先在操作系统提示符E:\下输入imp,然后IMPORT工具会一步一步提示用户回答系统提出的问题,根据用户的回答,IMPORT工具一步一步往下执行装入相应的内容。

下列命令将e:\oracle\ff.dmp文件中所包含的数据,根据需要将DEPT和emp 表装入到scott用户中。为避免出错,应该事先删除DEPT和emp 表,或者删除这两张表中的数据。

E:\>imp

Import:Release 9.2.0.1.0-Production on 星期三1 月19 12:02:18 2005

(c)Copyright 1982,2002,Oracle Corporation.All rights reserved.

用户名:scott/tiger

连接到:Oracle9i Enterprise Edition Release 9.2.0.1.0-Production

With the Partitioning and Java options

PL/SQL Release 9.2.0.1.0-Production

导入文件:EXPDAT.DMP>e:\oracle\ff.dmp

输入插入缓冲区大小(最小为8192)30720>

只列出导入文件的内容(yes/no):no>

由于对象已存在,忽略创建错误(yes/no):no>yes

导入权限(yes/no):yes>

导入表数据(yes/no):yes>

导入整个导出文件(yes/no):no>

用户名:scott

输入表(T)或分区(T:P)名称。空列表表示用户的所有表>dept

输入表(T)或分区(T:P)名称。空列表表示用户的所有表>emp

……

(2)命令行方式

命令行方式就是将交互方式中所有用户回答的内容全部写在命令行上,每一个回答的内容作为某一关键字的值。IMPORT工具命令行的语法如下:

IMP[KEYWORD]{VALUE|(VALUE,VALUE……)}

[[[,]KEYWORD]{VALUE|(VALUE,VALUE……)}]……

其中:KEYWORD是关键字,VALUE是为关键字赋的值。

IMPORT工具常用的关键字包括:USERID、TABLES、FILE、IGNORE、FULL、FROMUSER和TOUSER。其中USERID、TABLES、FULL关键字的含义与EXPORT工具中一致,这里不再解释。

FILE指定在EXPORT工具卸出时存储卸出内容的专门操作系统文件。

FROMUSER指定卸出对象的用户列表。

TOUSER指定需要装入对象的用户列表。只有拥有IMPFULLDATABASE角色权限的用户才能使用此关键字,将对象装入到其他用户账号中。

IGNOREY表示在装入过程中建立对象时忽略错误。在这种情况下,装入会继续,没有报告错误。对表来说,IGNOREY可以将行装入到已经存在的表中,没有给出任何消息。假如该对象已经存在时,如果IGNOREN会产生一个错误。

例8-49 用命令行方式导入C:\oracle\emp.dmp文件中的dept和emp表。用户scott按表模式从卸出文件emp.dmp中读取dept和emp两张表的数据装入到数据库中,并且忽略对象建立时的错误。

C:\IMP USERIDscott/tiger TABLES(dept,emp)FILEc:\oracle\emp.dmp

LOGexp.log IGNOREY

(3)参数文件方式

参数文件就是存放上述关键字和相应值的一个文件,该文件名作为命令行的PARFILE关键字的值。如果在参数文件中没有列出的关键字,该关键字就采用其默认值。

例8-50 用参数文件方式导入scott用户的dept和emp表。先编辑一个参数文件,名为C:\PAR2.TXT,内容如下:

USERIDscott/tiger

TABLES(dept,emp)

FILEC:\oracle\ff.dmp

LOGC:\oracle\ff.log

FROMUSERscott

TOUSERjohn

然后执行IMPORT工具时使用该参数文件(包含路径)。表示按表模式将scott用户卸出的dept、emp表装入john用户中,装入过程中的消息写到ff.log文件中。只有拥有IMPFULLDATABASE角色权限的用户才能将某一用户的对象装入到其他用户中。执行命令如下:

C:\IMP PARFILEC:\PAR2.TXT

8.3 数据库的并发性控制

数据库是一个共享资源,可以供多个用户使用。多个用户的事务可以串行地执行,即每个时刻只有一个事务在运行和存取数据库中的数据。此时许多资源都处于空闲状态。为了充分利用数据库资源,应该允许多个用户程序并发地执行,并发地存取数据库中的数据。

在多用户共享系统中,多个用户同时对同一数据进行操作称为并发操作。并发操作时,由于多个事务的操作是随机调度的,事务之间可能有干扰,破坏了事务的隔离性。DBMS的并发控制子系统负责正确调度并发事务的操作,使事务之间不受干扰,保证数据的一致性不受破坏,避免用户得到不正确的数据。

8.3.1 并发控制的原理和方法

8.3.1.1 并发操作带来的问题

下面先看一个实例,说明并发操作带来的数据不一致问题。

例如,考虑飞机订票系统中的一个活动序列:

①甲售票点(甲事务)读出某航班的机票余额A,设A50;

②乙售票点(乙事务)读出某航班的机票余额A,也为50;

③甲售票点卖出10张机票,修改余额AA-10,所以A 为40,把A写回数据库;

④乙售票点也卖出10张机票,修改余额AA-10,所以A 为40,把A写回数据库;

结果明明卖了20张机票,但数据库中机票余额只减少10。

这种情况称为数据库的不一致性。这种不一致性是由并发操作引起的。在并发操作的情况下,对甲、乙两个事务操作序列的调度是随机的。如果按上述调度序列执行,甲事务的修改被丢失。

仔细分析并发操作带来的数据不一致性包括三类:丢失更新问题、不可重复读问题和读“脏”数据问题。

1.丢失更新问题

丢失更新问题是指两个事务T1和T2读入同一数据并分别更新,T2提交的更新结果破坏了T1提交的更新结果,导致T1的更新被丢失。

事务T1(对应甲事务)和事务T2(对应乙事务)同时对A(机票数)的值更新。A的初值是50,事务T1卖出10张票,对A的值减10。事务T2也卖出10张票,对A的值也减10。结果A的值是40,而不是30,这是错误的。原因是在第8步丢失了事务T1对数据库的更新操作。

2.不可重复读问题

不可重复读问题是指事务T1读取数据后,事务T2执行更新操作,使得T1无法再现前一次读取的结果(即T1两次读取的数据不一样)。

当事务T2按某种条件读取数据库中的某些记录值后,由于另一个事务T1更新这些记录,或者删除这些记录,或者插入了新记录。而导致事务T2仍按原条件读取数据时,发现前后两次读取的数据不一致。这就是不可重复读问题。

3.读“脏”数据问题

读“脏”数据问题是指事务T1修改某一数据,并将其写回磁盘。事务T2读取同一数据后,T1由于某种原因被撤销,这时T1已修改过的数据恢复原值,T2读到的数据就与数据库中的数据不一致,则T2读到的数据就称为“脏”数据,即不正确的数据(即未提交且又被撤销的数据)。

事务T2读取了未提交的A的值40。紧接着,事务T1做了回退(ROLLBACK)操作,把A的值恢复为50。而事务T2仍在使用被撤销前的A的值40。在数据库技术中,未提交随后又被撤销的数据称为“脏数据”。

产生上述三类数据不一致的主要原因是并发操作破坏了事务的隔离性。并发控制就是要用正确的方式调度并发操作,使一个事务的执行不受其他事务的干扰,从而避免造成数据的不一致性。

并发控制的主要技术是封锁(LOCK)技术。

8.3.1.2 封锁的机制和原理

封锁是实现并发控制的一个非常重要的技术。封锁就是事务T在对某一对象操作之前,向系统发请求,请求对该对象加锁。加锁后事务T就对该对象有了一定的控制,在事务T释放它的锁之前,其他事务不能更新此对象。

1.封锁的类型

封锁的类型有两类:排他锁(exclusive,简称X锁)和共享锁(share,简称为S锁)。

(1)排他锁(X锁)

排他锁又称为写锁。如果事务T对数据对象A实现了X封锁,则只允许T读取和修改A的数据。在T解除A上的X封锁之前,其他事务不能对A加任何类型的锁。这就保证其他事务在T释放A上的锁之前不能读取和修改A的数据。只有获得X锁的事务才能对被封锁的对象进行更新。

LOCK X(R)命令表示给对象R加X锁。加锁是否成功取决于R上是否已有其他锁。

(2)共享锁(S锁)

共享锁又称为读锁。若事务T对数据对象A加上S锁,则事务T可以读取A的数据,但不能修改A的数据。在T释放A上的S锁之前,其他事务只能对A加S锁,不能加X锁。这就保证事务T对数据对象A加S锁后,其他事务可以读A的数据,但不能对A进行任何更新操作。

LOCK S(R)命令表示给对象R加S锁。加锁是否成功取决于R上是否已有其他锁。

2.活锁和死锁

和操作系统一样,封锁的方法可能引起活锁和死锁。

(1)活锁

可能存在某个事务永远处于等待状态,得不到执行,这种现象称为活锁。

例如:事务T1封锁对象R,事务T2又请求封锁R,于是T2等待。T3也请求封锁R,当T1释放R上的封锁之后系统首先批准了T3的请求,T2仍然在等待。然后T4又请求封锁R,当T3释放R上的封锁之后系统又批准了T4的请求……,T2有可能永远处于等待,这就是活锁的情形。

避免活锁的方法是采用“先来先服务”的策略。当多个事务请求封锁同一对象时,封锁子系统按请求封锁的先后次序对事务进行排队。对象上的锁一旦释放,就批准申请队列中第一个事务获得锁。

2.死锁

两个或两个以上的事务都处于等待状态,每个事务都在等待另一个事务解除封锁,它才能执行下去,结果任何一个事务都无法执行,这种现象称为死锁。

例如,事务T1封锁对象R1,T2封锁对象R2;然后T1又请求封锁R2,因为R2已被T2封锁,所以T1等待T2释放R2上的锁;接着T2又申请封锁R1,因为R1被T1 封锁,所以T2等待T1释放R1上的锁。这样出现了T1等T2释放锁,T2又等T1释放锁的局面。T1和T2两个事务永远不能结束,形成死锁。

解决死锁的一种方法是采取一定的措施预防死锁的发生。另一种方法是定期检查是否发生死锁,如果发现发生了死锁,那么只能抽出某个事务作为牺牲品,将该事务撤销,做回退操作。撤销时解除该事务所有的锁,恢复到该事务的初始状态。此时其他事务可以获得相应的锁,有可能消除死锁现象。

3.封锁协议

在运用X锁和S锁对数据对象加锁时,需要约定一些规则,这些规则称为封锁协议。封锁协议就是规定什么时候可以申请加锁,锁定多长时间,以及什么时候释放锁等内容。对不同的封锁方式规定不同的规则,形成了各种不同的封锁协议。下面介绍三种封锁协议。这三种封锁协议在不同程度上解决并发操作所引起的丢失更新、不可重复读、读“脏”数据等问题,保证了并发操作的正确调度。

(1)一级封锁协议(即PXC协议)

一级封锁协议指:事务T在修改数据A之前必须先对A加X锁(可用LOCK X(A)命令),直到事务结束才释放X锁;如果得不到锁,则等待。COMMIT和ROLLBACK操作结束事务。(即修改前先获得X锁,得不到锁就等待。此锁只能由COMMIT或ROLLBACK命令释放,不能通过UNLOCK命令释放锁。)

一级封锁协议可防止丢失更新问题,并保证事务T是可恢复的。

当事务T2在时间点4时请求对A加X锁被拒绝,T2只能等待T1释放A上的锁后才能获得对A的X锁。事务T1在时间点7时提交对A的修改,并释放锁,此时数据库中A的值为修改后的值40。事务T2在时间点9时获得对A的X锁,读取的数据A为T1更新后的值40,再对新值40进行运算,并将结果30写入磁盘。这样避免事务T1的更新被丢失问题。

一级封锁协议规定:更新操作之前必须先获得X锁,但读数据是不需要加锁的,所以使用一级封锁协议可以解决丢失更新问题,但不能解决不可重复读、读“脏”数据等问题。

(2)二级封锁协议(即PS协议)

二级封锁协议指:在一级封锁协议的基础上,再加上事务T在读取数据A之前必须先对其加S锁,读完后释放S锁。(即修改之前加X锁,直到事务结束才释放X锁。锁不到,等待。读数据之前加S锁,读完后就释放S锁。锁不到,就等待。)

二级封锁协议除解决丢失更新问题外,还可以解决读“脏”数据问题。

修改A的值之后写回磁盘。这时事务T2在时间点6时请求在A上加S锁,因为T1已在A上加了X锁,T2不能加S锁,所以T2只能等待。T1在时间点8时撤销了刚在的修改操作,此时A的值恢复为50,T1释放A上的X锁。在时间点10时T2获得A上的S锁,读取A值为50。这就避免T2读“脏”数据。

由于二级封锁协议中读完数据后即释放S锁,所以不能解决“不可重复读”问题。

3.三级封锁协议(即PSC协议)

三级封锁协议指:一级封锁协议基础上,再加上事务T在读取数据A之前必须先对其加S锁,直到事务结束才释放锁。(即修改数据之前加X锁,直到事务结束才释放X锁。锁不到,等待。读数据之前加S锁,直到事务结束才释放S锁。锁不到,等待。)

4.并发调度的可串行性

安排事务的执行次序的过程称为调度。对多个事务的调度方式分为串行调度和并行调度两种。串行调度即一次只执行一个事务,当该事务执行完后才执行其他事务。并行调度即利用分时的方法同时执行多个事务,利用封锁技术保证并发操作时数据的一致性。

对于事务集(T1,T2……,Tn),如果一个并发调度的结果与某一个串行调度的执行结果等价,则称此并发调度是可串行化的调度。对于某事务集的一个并发调度结果如果与任一串行调度均不等价,则该调度是不可串行化调度。

只有可串行化的并行操作是正确的,而不可串行化的将破坏数据的一致性(可串行化是并行事务正确性的准则。表8-18给出了两个事务的三种不同的调度策略。

5.封锁的粒度

封锁对象的大小称为封锁粒度。封锁对象可以是数据库、表、数据页、行、列等单元。封锁粒度与系统的并发度和并发控制的开销密切相关。一般情况,封锁的粒度越大,数据库所能封锁的数据单元就越小,并发度越小,系统开销也越小;反之,封锁粒度越小,数据库并发度越大,系统开销也越大。

如果封锁的粒度是行,则事务T1和T2可同时对表L中不同的行加锁,事务间不需要等待,并发度就高。如果事务要读取整个表L,而封锁粒度是行,则必须对表中每一行加锁,显然系统开销很大。

一个系统中应支持多种封锁粒度供不同事务选择。如果需要处理大量元组的事务应该以表为封锁粒度。如果只处理少量元组的事务应该以元组为封锁粒度。

8.3.2 Oracle系统中并发控制技术

8.3.2.1 Oracle的封锁方式

Oracle给表加锁有两种方式:手工封锁和自动封锁。

1.自动封锁

当某一会话对表进行插入、更新、删除操作时,系统会自动分配一个行独占锁(RX锁),并且当插入、更新、删除操作完成并结束事务时,系统会自动释放锁资源。此时允许其他用户获得锁资源。当某一会话执行SELECT FOR UPDATE语句时,系统自动分配一个行共享锁(RS锁),当事务结束时,系统自动释放锁资源。

2.手工封锁

除了RX锁可以自动获得,行共享锁可以通过SELECT FOR UPDATE命令自动获得外,其他的共享锁(S锁)、独占锁(X)都只能通过LOCK TABLE语句获得。通过LOCK TABLE语句还可以获得行共享锁(RS锁)、行独占锁(RX锁)。使用LOCK TABLE语句可以锁定整个表,防止其他会话在表上完成DML操作。LOCK语句的语法如下:

LOCK TABLE[用户名,]表名IN

{SHARE|ROW SHARE|EXCLUSIVE|ROW EXCLUSIVE}

MODE[NOWAIT];

锁定可以采用共享模式或独占模式。共享模式可以防止其他会话获得独占锁,但允许其他会话获得一个共享锁。独占模式既可防止其他会话获得共享锁,又可防止其他会话获得独占锁。例如:

LOCK TABLE scott.emp IN EXCLUSIVE MODE;

对数据进行更新时需要对更新的行加独占锁,可以通过LOCK TABLE语句加独占锁,也可以由系统自动加独占锁。当更新操作完成后,应该释放独占锁。如果是通过LOCK TABLE语句加的独占锁,必须用UNLOCK语句显式地释放锁,否则会增加死锁的概率。如果是系统自动加的独占锁,则事务结束时,系统自动释放独占锁,所以最好采用自动封锁。

8.3.2.2 Oracle封锁类型

Oracle使用DML锁来管理并发操作,即管理多个会话同时修改相同数据的操作。Oracle既使用表级锁,又使用行级锁。行级锁总是独占性的,而表级锁既可以是共享的,也可以是独占性的。共享锁会防止出现其他独占性锁,但允许其他共享锁。独占性锁既会防止出现其他独占性锁,也防止出现其他共享锁。但是任何DML锁都不阻挡读取访问。为了更改数据,Oracle 必须在要进行更改的行中采用独占锁。INSERT、UPDATE、DELETE和SELECT FOR UPDATE语句都会隐式加上必要的行级锁。

(1)行共享锁(RS)

行共享锁是通过一个SELECT FOR UPDATE语句隐式获得的,或者通过一条LOCK TABLE IN ROW SHARE MODE语句显式获得的。行共享锁并不防止对数据进行更新,但可以防止其他会话获得独占锁。

(2)行独占锁(RX)

行独占锁是通过一条INSERT、UPDATE、DELETE语句隐式获得的,或者通过一条LOCK TABLE IN ROW EXCLUSIVE MODE语句显式获得的。独占锁可以防止其他会话获得一个共享锁、独占锁。

(3)共享锁(S)

共享锁是通过一条LOCK TABLE IN SHARE MODE语句显式获得的。共享锁可以防止其他会话获得行独占锁、独占锁,但允许其他会话在表上加共享锁和行共享锁。

(4)独占锁(X)

独占锁是通过一条LOCK TABLE IN EXCLUSIVE MODE语句显式获得的。独占锁可以防止其他会话获得对该表的任何共享锁和独占锁。其他会话只能从被独占锁锁定的表中进行选择操作。

在时间点202时,alan用户执行LOCK TABLE语句,希望获得emp表的X锁,此时显示一个错误,告诉用户资源忙,没有获得X锁,等待molly的会话释放锁资源。

在时间点203时,molly用户执行COMMIT操作结束事务,释放emp表的RX锁。此时alan用户马上获得emp表的X锁。

在时间点204时,molly用户执行UPDATE语句,需要获得RX锁,由于alan用户获得了emp表的X锁,阻止molly用户获得RX锁,所以molly用户等待alan会话释放锁。

在时间点205时,alan用户执行ROLLBACK操作结束事务,释放emp表的X锁。此时molly用户马上获得RX锁,完成更新操作。然后molly用户执行COMMIT操作结束事务,并释放emp表的RX锁。

在时间点206时,molly用户执行LOCK TABLE语句获得emp表的RS锁。

在时间点207时,alan用户执行INSERT INTO 语句,隐式获得emp表的RX锁。因为某一用户给表加了RS锁,并不阻止其他用户给表加RX锁。所以alan用户的INSERT操作允许。

在时间点208时,alan用户执行COMMIT操作结束事务,并释放emp表的RX锁。

在时间点209时,molly用户执行LOCK TABLE语句获得emp表的S锁。

在时间点210时,alan用户执行INSERT INTO 语句,需要隐式获得emp表的RX锁。因为molly用户已给表加了S锁,阻止其他用户再给emp表加RX锁,所以处于等待状态。

在时间点211时,molly用户执行COMMIT操作结束事务,并释放锁资源。

在时间点212时,alan用户执行COMMIT操作结束事务,并释放锁资源。

8.3.2.3 Oracle死锁检测机制

当两个事务都加了锁,并且各自等待着对方会话所锁定的一个资源时,就会出现死锁。

8.4 数据库的完整性控制

数据库的完整性是指数据的正确性和相容性,可以防止不符合语义的数据输入和输出所造成的无效操作和错误结果。DBMS必须提供一种机制来检查数据库中的数据是否满足语义规定的条件,保证数据库中的数据是正确的。这种语义规定的条件称为数据库完整性约束条件。

8.4.1 完整性约束的概念

语义规定的条件称为数据库完整性约束条件,完整性约束条件是DBMS完整性子系统的核心。完整性子系统的主要功能如下。

定义功能:提供定义完整性约束的机制。

检查功能:检查用户发出的操作请求是否违反完整性约束。

处理功能:如有违反现象,则采取一定的动作来保证数据的完整性,如拒绝操作或改正错误等方法来处理。

8.4.1.1 SQL完整性约束的类型

在关系数据库系统中完整性约束分为实体完整性、参照完整性和用户定义的完整性。在SQL语言中,根据约束所完成的功能不同,表达完整性约束的规则有主键约束、外键约束、属性约束等几类。

1.主键约束

主键约束是数据库中最重要的一种约束。主键约束体现了实体完整性。要求某一列的值既不能为空,也不能重复。

例8-52 创建包含主键约束的表。

SQL>CREATE TABLE student(sno char(8)PRIMARY KEY,/*主键约束*/

sname char(20)NOT NULL,/*非空约束*/

*** char(1),

age int,

dept char(15))

2.外键约束

外键约束体现参照完整性。外键的取值或者为空,或者参考父表的主键。

在实际应用中,作为主键的关系称为父表(或被参照表)。作为外键的关系称为子表(或参照表)。

例8-53 sc表中sno和cno是主键。sno和cno分别是外键,参照student表和course表的sno和cno列。

SQL>CREATE TABLE sc(sno char(5),

cno char(8),

grade smallint,

PRIMARY KEY(sno,cno),/*主键约束*/

FOREIGN KEY(sno)references student(sno),/*外键约束*/

FOREIGN KEY(cno)references course(cno),/*外键约束*/

CHECK((grade is null)or(grade between 0 and 100)))

/*CHECK约束*/

3.属性约束

属性约束体现用户定义的完整性。属性约束主要限制某一属性的取值范围。属性约束可分为以下几类。

非空值约束:要求某一属性的值不允许为空值。例如:sname要求非空。

唯一值约束:要求某一属性的值不允许重复。如果某一属性是主键,则该属性的值不能为空值,而且要唯一。例如:SNO要求唯一。

基于属性的CHECK约束:在属性约束中的CHECK约束可以对一个属性的值加以限制。限制就是给某一列设定的条件,只有满足条件的值才允许插入。例如:要求成绩(GRADE列)要么是空,表示还没有成绩,要么在0到100之间。

8.4.1.2 完整性约束的定义

完整性约束的定义可以用DDL语言在建表时描述,也可以使用“ALTER TABLE 表名ADD CONSTRAINT”命令添加新的约束。当表定义完时,一条完整性约束被系统存放在数据字典中。当用户进行操作时,系统就开始检查,如果发现用户操作违反约束条件,系统处理违反情况,而不用用户处理。

例8-54 在DDL语句中定义完整性约束条件。

SQL>CREATE TABLE student(sno char(8)PRIMARY KEY,

sname char(20)NOT NULL,

*** char(1),

age int,

dept char(15))

当建表时系统自动为主键约束命名,并存入数据字典。

例8-55 sc表加一个约束条件,限制sc表的SNO值必须从student表中获取。

SQL>ALTER TABLE sc ADD CONSTRAINT sccheck

CHECK(sno IN(SELECT sno FROM student))

8.4.1.3 完整性约束的命名

为了便于对约束进行管理和操作,最好给每个约束取个名字。取名的方法是在定义时,在约束前加一个关键字CONSTRAINT和约束名即可,此时用用户自定义的约束名替代系统命名的约束名。

例8-56 为约束条件命名。

SQL>CREATE TABLE student(sno char(8)CONSTRAINT spk PRIMARY KEY,

sname char(20)CONSTRAINT snn NOT NULL,

*** char(1),

age int,

dept char(15))

上述语句给主键取名为SPK,给非空约束取名为SNN。

8.4.1.4 完整性约束的撤销

在关系定义后,可以通过某些语句添加新的约束和撤销约束。“ALTER TABLE 表名ADD CONSTRAINT”命令用于添加新的约束,“ALTER TABLE 表名DROP CONSTRAINT”命令用于撤销已有的约束。当撤销约束时,系统从数据字典中删除该约束的定义。

例8-57 删除student表中的主键约束spk。

SQL>ALTER TABLE student DROP CONSTRAINT spk

8.4.2 Oracle中的完整性约束

8.4.2.1 Oracle中保证完整性的方法

在Oracle系统中保证数据完整性有三种主要的方法:应用代码、数据库触发器和定义完整性约束。

1.应用代码

应用代码可以通过存储过程实现,也可以通过运行在客户端的应用程序实现。存储过程和应用程序的编写参见第6章和第7章。

2.数据库触发器

数据库触发器是一段PL/SQL程序,当一张表上插入数据、删除数据或更新表中某一列时就执行这段程序。通常只有在定义完整性约束条件不能满足复杂的业务规则时才建立数据库触发器。触发器的编写参见第7章。

3.定义完整性约束

完整性约束可以改善性能、不需要编写代码、很灵活,可以根据需要让约束条件生效或失效,完整性的文档都记录在数据字典中。由于完整性约束有上述优点,本节主要介绍完整性约束方法。

同类推荐
  • 无人机:知道这些就够了

    无人机:知道这些就够了

    不久的将来无人机将像智能手机一样司空见惯,而你对无人机的了解有多少?你知道无人机有哪些用途吗?无人机对你和你的家庭又会产生什么样的影响呢?知道这些就够了。
  • 虚拟现实:下一个产业浪潮之巅(第2版)

    虚拟现实:下一个产业浪潮之巅(第2版)

    毫无疑问,虚拟现实时代已经来临,VR不仅将彻底改变人们交互的方式。而且会是互联网的下一个风口,VR会创造新时代,即由人的体验构成的互联网时代。目前,全球范围众多的科技、影视等商业巨头纷纷砸巨资押注VR产业。例如,扎克伯格越来越坚定地认为,VR将会成为下一代计算机平台;任正非在内部讲话中也提到,华为要保持理性地进行VR投入与研究,要在这个充满诱惑的领域里分得一杯羹,谁最后倒下,谁便赢得天下。本书是作者基于VR行业多年的研究以及创立VR公司的经验写成,目的是让读者快速、全面地了解VR产业最新、最重要的信息,如生态链、技术瓶颈、发展前景以及人才结构等,是一部不可多得的VR行业入门读物。
  • 云计算、网络安全和网络盗窃:网络世界防盗初学指南

    云计算、网络安全和网络盗窃:网络世界防盗初学指南

    网络犯罪层出不穷,保护自己的安全,防止受到攻击,似乎是一个艰巨的任务。幸运的是,有一些人人都能采取的措施,可以降低成为网络袭击对象的风险。保证基于云计算程序的安全和降低被袭击的风险,关键在于理解云安全的共同责任。云提供商需要全力确保实施尽可能严格的安全策略。
  • 信息革命

    信息革命

    随着经济社会的快速发展,电子产品走进了千家万户,与电子产品相伴的信息技术也已渗透到人们生产生活的方方面面。加强信息技术普及,已成为业内人士的共识。鉴于此,在有关部门的大力支持下,经过认真筹划,我们编辑出版了《信息革命》一书。该书以时间为经,在记述信息技术发展历程的同时,深入浅出地介绍了信息技术的相关知识,对人们更好地利用现代信息技术服务经济社会建设和个人生产生活必将产生积极作用。本书由李大东主编。
热门推荐
  • 空灵道劫

    空灵道劫

    讲述男主通过修炼拯救同门击败强敌的故事!
  • 穿越之妈咪带我闯江湖

    穿越之妈咪带我闯江湖

    十年前,一场穿越时空,让江美美找到了真爱,但是无奈命运弄人,自己却又被迫离开爱人,回到现代。十年后,还是穿越时空,但却不是江美美一个,还附带一个拖油瓶儿子,寻找爱人的同时,这对宝贝却把江湖搞了个天翻地覆。十年前,莫御辰爱上了美丽可爱的现代女人。十年后,痛失爱人的他创立了势力强大的组织冷情山庄,却也想不到被一个九岁孩子搞得无可奈何。守候十年的爱情,如何再重圆,古灵精怪的天才儿童,如何玩转江湖。自由一番妙趣。
  • 永恒玩家国度

    永恒玩家国度

    这是一个怎么样的世界?这是一个混乱不堪的世界;这是一个充满罪恶的世界;这是一个需要巨人的世界,但这个世界没有巨人。于是乎,我们的主角来了,虽然他不是巨人,也不想当巨人……(高清版)但他的身后,尽是巨人……(注:本书不圣母,不种马)
  • 顾太太你好甜呀

    顾太太你好甜呀

    (甜宠爽文)婚前,顾阎王忙着列规矩。第一:不准爱上我。第二:不准进我的卧室。第三:不准靠近我三步之内。......婚后,啪啪啪打脸。拍卖会上,顾阎王为沈瑜兮拍下最昂贵的蓝宝石项链,高调宣称:这么漂亮的宝石只有我老婆配得上。颁奖典礼上,顾阎王搂着沈瑜兮一脸献媚:我老婆棒棒哒。......冷酷霸总,傲娇男神恨不得终日将老婆系在裤腰带上。
  • 凡人(菲利普·罗斯全集)

    凡人(菲利普·罗斯全集)

    “老年不是一场战斗;老年是一场大屠杀。”菲利普·罗斯晚期代表作,写尽凡俗人世的悲愤与无奈,多家欧美权威书评媒体倾力推荐。《凡人》的书名源自一部中世纪道德剧,讲述一个“凡人”被死亡召唤时的临终经历。罗斯的《凡人》则是一个关于失去与悔憾、病痛与死亡的故事。小说的主角曾是纽约一家广告公司的创意总监,有过三次失败的婚姻,两个仇视他的儿子和一个挚爱他的女儿。他还有一个随时照顾他的好哥哥,其健康的体魄甚至令他妒忌。从童年的夏季在海边初次见证死亡,到精力旺盛的成年时代事业上的成功、几次婚姻家庭的聚散,再到步入老年看着同代人日渐凋零、自己屡遭病变,孤独和无力感成了他生活的主题。这就是罗斯笔下“凡人”的一生,坦率、深沉,又具有普遍意义。
  • 灵度录

    灵度录

    有着别人看不见的东西,寻找着奇妙的东西,度过着迷茫的东西,眼前也许什么都没有
  • 英雄皇冠

    英雄皇冠

    电子竞技,无数承载了无数九零后梦想的地方。我们会为了一次胜利,简单的两个字而付出,数年的努力。假如,你问为什么?我会告诉你。有梦想的地方!那就是天堂。
  • 反派Boss的黑月光

    反派Boss的黑月光

    (1V1苏撩甜宠文打脸爽文)林深时见鹿,海蓝时见鲸,梦醒时见你,是我能想到的最好的生活状态。——秦悠然 因为有你,纵然是十八层地狱,我也要闯,这是我对你的承诺。——反派BOSS ——————————————月光的照耀下,朦胧的影子上,女孩儿樱唇轻启,无害甜美的笑容却很是渗人。“连你……也要抛弃阿然了么……”暖黄色的日光灯下,女人眼角流出一滴眼泪,滑落至锁骨,笑容凄惨。“原来一切都只不过是我的自作多情……”星光璀璨下,女子望了一眼星辰,不明的笑容。“终究,在你眼里,看不见我要的星辰大海!”——————————————反派BOSS:“投诉!宿主随处乱撩,蛊惑人心!”系统748:【自家宿主太难管啦,表示天天生活在水深火热之中,强烈要求退货!】秦悠然:“作死撩汉是我毕生的追求……”
  • 苏灿灿的盛夏

    苏灿灿的盛夏

    苏灿灿是一个双鱼座的女生,和大多数普通女生一样快乐的长大了,但是她的情感之路好像并不那么顺利,谈恋爱从来没超过三个月,总是会以失败告终……直到他大二那年遇到了云深,他们之间的故事就开始了……
  • 重生之将门养女

    重生之将门养女

    新手一枚,请多多指教。我不知道未来会怎样,但是我觉不会后悔我现在的决定。加油加油加油!ε=ε=(ノ≧?≦)ノ2020我来了