Oracle中读一致性描述的一些困惑
Some confusion on the description of read consistency in Oracle
以下是 oracle 概念指南中关于读取一致性的简短介绍。
什么是sql语句,就一个sql?或者Pl/SQL或者存储过程?谁能帮我提供一个相反的例子来说明读取不一致?
read consistency
A consistent view of data seen by a user. For example, in statement-level read
consistency the set of data seen by a SQL statement remains constant throughout
statement execution.
在此上下文中,一个 "statement" 是一个 DML 语句:单个 SELECT
、INSERT
、UPDATE
、DELETE
、MERGE
.
它不是一个PL/SQL块。同样,同一 DML 语句的多次执行(例如,在 PL/SQL 循环中)是分开的 "statements"。如果您需要多个语句或 PL/SQL 块内的一致性,您可以使用 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
或 SET TRANSACTION READ ONLY
来实现。两者都引入了限制。
不一致读取的相反示例如下。
起始条件:table BIG_TABLE
有 1000 万行。
10:00 的用户 A:
SELECT COUNT(*) FROM BIG_TABLE;
10:01 的用户 B:
DELETE FROM BIG_TABLE WHERE ID >= 9000000; -- delete the last million rows
10:02 的用户 B:
COMMIT;
10:03 的用户 A:查询完成:
COUNT(*)
--------------
9309129
这是错误的。用户 A 应该获得 1000 万行或 900 万行。 table 中从来没有 9309129 提交 行。发生的事情是,在 Oracle 实际处理删除之前(或在 COMMIT
之前),用户 A 已经读取了用户 B 正在删除的 309,129 行。然后,在用户 B delete/commit 之后,用户 A 的查询不再看到删除的行并停止计数。
由于多版本读取一致性的实现,这种问题在 Oracle 中是不可能的。
在 Oracle 中,在上述情况下,当遇到用户 B 删除(和提交)行的块时,用户 A 的查询将使用 UNDO 数据重建这些块在 10:00 时的样子-- 用户A开始查询的时间。
基本上就是这样 -- Oracle 语句在数据库的一个版本上运行,因为它存在于单个时间点。这个时间点几乎总是语句开始的时间。当该时间点将移动到时间点 "mid statement" 时,存在一些涉及更新的异常情况。但它始终与某个时间点或另一个时间点一致。
以下是 oracle 概念指南中关于读取一致性的简短介绍。
什么是sql语句,就一个sql?或者Pl/SQL或者存储过程?谁能帮我提供一个相反的例子来说明读取不一致?
read consistency
A consistent view of data seen by a user. For example, in statement-level read
consistency the set of data seen by a SQL statement remains constant throughout
statement execution.
在此上下文中,一个 "statement" 是一个 DML 语句:单个 SELECT
、INSERT
、UPDATE
、DELETE
、MERGE
.
它不是一个PL/SQL块。同样,同一 DML 语句的多次执行(例如,在 PL/SQL 循环中)是分开的 "statements"。如果您需要多个语句或 PL/SQL 块内的一致性,您可以使用 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
或 SET TRANSACTION READ ONLY
来实现。两者都引入了限制。
不一致读取的相反示例如下。
起始条件:table BIG_TABLE
有 1000 万行。
10:00 的用户 A:
SELECT COUNT(*) FROM BIG_TABLE;
10:01 的用户 B:
DELETE FROM BIG_TABLE WHERE ID >= 9000000; -- delete the last million rows
10:02 的用户 B:
COMMIT;
10:03 的用户 A:查询完成:
COUNT(*)
--------------
9309129
这是错误的。用户 A 应该获得 1000 万行或 900 万行。 table 中从来没有 9309129 提交 行。发生的事情是,在 Oracle 实际处理删除之前(或在 COMMIT
之前),用户 A 已经读取了用户 B 正在删除的 309,129 行。然后,在用户 B delete/commit 之后,用户 A 的查询不再看到删除的行并停止计数。
由于多版本读取一致性的实现,这种问题在 Oracle 中是不可能的。
在 Oracle 中,在上述情况下,当遇到用户 B 删除(和提交)行的块时,用户 A 的查询将使用 UNDO 数据重建这些块在 10:00 时的样子-- 用户A开始查询的时间。
基本上就是这样 -- Oracle 语句在数据库的一个版本上运行,因为它存在于单个时间点。这个时间点几乎总是语句开始的时间。当该时间点将移动到时间点 "mid statement" 时,存在一些涉及更新的异常情况。但它始终与某个时间点或另一个时间点一致。