整理自Oracle 11g R2 官方文档《concepts》
001 简介
001 简介
在单用户的数据库中,用户可以修改数据,而不用担心其它用户在同一时间修改相同的数据。但是,在一个多用户的数据库中,多个事务内的语句可以同时更新相同的数据。同时执行的多个事务必须产生有意义且一致的结果。因此,多用户数据库必须提供以下功能:
·数据并发性:确保多个用户可以同时访问数据
·数据一致性:确保每个用户看到数据的一致的视图,包括可以看到用户自己的事务所做的更改,和其它用户已提交的事务所做的更改。
为描述当多个事务同时运行时的事务一致性行为,数据库研究人员定义了一种称为可串行性的事务隔离模型。可串行化事务在一种使其看起来好像没有其他用户正在修改数据库中的数据的环境中运作。
虽然事务之间的这种隔离度好像不错, 但在可序列化模式下运行许多应用程 序可能会严重影响应用程序吞吐量。对并发运行事务的完全隔离可能意味着一个事务无法在某个正在被另一个事务查询的表上执行插入操作。简而言之,现实的考虑通常需要在完美的事务隔离性和性能之间的一个折衷。
Oracle 数据库通过使用多版本一致性模型和各种类型的锁和事务,来维护数据的一致性。通过这种方式,数据库可以向多个并发用户呈现一个数据的视图,每个视图都在某个时间点上是一致的。因为不同版本的数据块可以同时存在,事务可以读取在某个查询请求时间点上的已提交版本数据,并返回符合一个单一时间点的结果。
002 多版本读一致性
在Oracle数据库中,多版本即同时实现数据的多个版本的能力。Oracle数据库维护多版本读取一致性,这意味着数据库查询具有以下特征:
·读一致查询
查询所返回的数据已提交的, 且关于某个单一时间点一致。Oracle 数据库绝不允许脏读。当一个事务读取了另一个事务中未提交的数据时,会发生脏读。为说明脏读的问题, 假设一个事务更新某列的值,但不提交。第二个事务读取此已更新的脏(未提交)值。第一个会话回滚了事务,使该列仍具有其旧值,但第二个事务继续使用更新的值, 这会损坏数据库。脏读会破坏数据的完整性、破坏外键、和忽略唯一约束。
·非阻塞查询
数据的读取者和写入者不会相互阻塞。
003 语句级读取一致性
Oracle 数据库始终强制执行语句级读取一致性,保证单个查询所返回的数据是已提交的、且关于某个单一时间点一致。 单个SQL 语句所一致的时间点取决于事务的隔离级别和查询的性质:
· 在读提交隔离级别,该时间点是语句打开的时间。例如,如果一个SELECT 语句在SCN 1000 时打开,则此语句一致于SCN 1000。
· 在可串行化或只读事务隔离级别,该时间点为事务开始的时间。例如,如果一个事务开始于SCN 1000,且在该事务中有多个SELECT 语句发生,则每个语句都一致于 SCN 1000。
· 在闪回查询操作(SELECT ... AS OF)中,SELECT 语句显式指定时间点。例如,你可以查询某个表在上星期四下午2时的数据。
004 事务级读取一致性
Oracle 数据库还可以为一个事务中的所有查询提供读取一致性,这称为事务级读取一致性。在这种情况下,事务中的每个语句都看到来自同一时间点(即该事务开始的时间)的数据。在一个可序列化事务中的多个查询,能看到事务本身所做的更改。例如,某 个事务更新了 employees 表,然后其后续查询将看到对 employees 所做的更新。事务级读取一致性产生可重复的读取,且不会产生幻读。
005 读取一致性及undo段
005 读取一致性及undo段
为管理多版本的读取一致性模型,当表同时被查询和更新时, 数据库必须创建一组读取一致的数据。Oracle 数据库通过使用undo数据实现了这一目标。
每当用户修改了数据,Oracle 数据库会创建撤销条目,并写入到undo段。undo段包含由未提交事务或最近提交的事务所更改的数据的旧值。因此,同一数据在各个不同时间点上的多个版本,都可以存在于数据库中。数据库可以使用在不同时间点的数据快照,来提供数据读取一致视图,并实现非阻塞查询。
读取一致性在单实例和Oracle 真正应用集群(Oracle RAC)环境中都可以得到保证。Oracle RAC 使用一种称为缓存融合的“缓存到缓存”的数据块传输机制,将一个数据库实例中的数据块读取一致映像传送到另一个实例中。
006 读一致性示例
每当用户修改了数据,Oracle 数据库会创建撤销条目,并写入到undo段。undo段包含由未提交事务或最近提交的事务所更改的数据的旧值。因此,同一数据在各个不同时间点上的多个版本,都可以存在于数据库中。数据库可以使用在不同时间点的数据快照,来提供数据读取一致视图,并实现非阻塞查询。
读取一致性在单实例和Oracle 真正应用集群(Oracle RAC)环境中都可以得到保证。Oracle RAC 使用一种称为缓存融合的“缓存到缓存”的数据块传输机制,将一个数据库实例中的数据块读取一致映像传送到另一个实例中。
006 读一致性示例
下图显示了一个查询,在已提交读隔离级别使用undo数据以提供语句级的读取一致性。
图 1 在已提交读隔离级别的读取一致性
当数据库为某个查询检索数据块时,数据库确保每个块中的数据反映了该查询开始时的内容。数据库根据需要回滚对数据块所做的更改,以将块重建到 查询处理开始的状态。
数据库使用一种称为SCN 的机制,来保证事务的顺序。当SELECT 语句进入执行阶段时,数据库会确定查询开始执行时所记录的SCN。在上图中,该SCN 为10023。在事务中的每个查询必须返回在SCN 10023 时的已提交数据。
在图1中,其SCN 大于10023 的块具有已更改数据,如图1中的两个具有SCN 10024 的块所示。SELECT 语句需要一个与已提交更改块一致的版本。该数据库将当前数据块复制到新的缓冲区,并应用撤消数据,以重新构造块的早期版本。这些重建的数据块被称为一致性读取 (CR) 克隆。
在图1中,数据库创建了两个CR 克隆:一个块与SCN 10006 一致,而另一个块与SCN 10021 一致。数据库为查询返回重建的数据。通过这种方式,数据库可以防止脏读。
007 读一致性和事务表
数据库使用一个事务表,也称感兴趣事务列表 (ITL) ,来确定当数据库开始修改块时是否某个事务还未提交。每个段块的块头包含一个事务表。
事务表中的条目描述了哪些事务有被锁定的行,以及块中的哪些行包含提交和未提交的更改。事务表指向undo段,提供对数据库所做的更改的时间相关信息。
在某种意义上,块头包含影响块中每个行的事务的最近历史记录。CREATE TABLE 和ALTER TABLE 语句的NITRANS 参数,控制被保留的事务历史记录条数。
008 锁定机制
通常,多用户数据库使用某种形式的数据锁定,来解决与数据并发性、一致性、和完整性相关的问题。 锁是防止访问同一资源的事务之间的破坏性相互作用的机制。
009 ANSI/ISO 事务隔离级别
已由ANSI 和ISO/IEC 采纳的SQL 标准,定义了四个事务隔离级别。这些级别对事务处理吞吐量有不同程度的影响。
这些隔离级别根据在同时运行的事务之间必须防止的现象来定义。可预防的现象有:
·脏读
一个事务读取了已被另一个事务写入、但尚未提交的数据。
·不可重复(模糊)读
一个事务重新读取之前曾经读取过的数据,发现另一个已提交的事务已修改或删除了该数据。例如,用户查询某行,然后稍后又查询相同的行,却发现数据已更改。
·幻像读
一个事务重新运行满足某搜索条件的查询,并返回一个行集,发现另一个已提交的事务已插入了满足搜索条件的其他行。
例如,一个事务查询雇员数目。五分钟后它执行相同的查询,但现在人数却增加了一个,这是因为另一个用户为一名新员工插入了一条记录。满足查询条件的数据比之前更多了,但与不可重复读不同,之前读取的数据不会变化。
根据运行在某个特定的隔离级别的事务所允许发生的现象,SQL 标准定义了四个隔离级别。表9-1 显示了这些级别。
Oracle 数据库提供了已提交读(默认值)和可串行化隔离级别。另外,数据库也可以提供一种只读模式。
这些隔离级别根据在同时运行的事务之间必须防止的现象来定义。可预防的现象有:
·脏读
一个事务读取了已被另一个事务写入、但尚未提交的数据。
·不可重复(模糊)读
一个事务重新读取之前曾经读取过的数据,发现另一个已提交的事务已修改或删除了该数据。例如,用户查询某行,然后稍后又查询相同的行,却发现数据已更改。
·幻像读
一个事务重新运行满足某搜索条件的查询,并返回一个行集,发现另一个已提交的事务已插入了满足搜索条件的其他行。
例如,一个事务查询雇员数目。五分钟后它执行相同的查询,但现在人数却增加了一个,这是因为另一个用户为一名新员工插入了一条记录。满足查询条件的数据比之前更多了,但与不可重复读不同,之前读取的数据不会变化。
根据运行在某个特定的隔离级别的事务所允许发生的现象,SQL 标准定义了四个隔离级别。表9-1 显示了这些级别。
Oracle 数据库提供了已提交读(默认值)和可串行化隔离级别。另外,数据库也可以提供一种只读模式。