Oracle 提供的读完整性包含以下特性:
保证在一个时间点上,用户通过查询语句得到的数据是一致的,且语句执行期间数据不会改变(语句级的读完整性)
保证数据库中读数据的用户无需等待正在读或写相同数据的用户。
保证数据库中写数据的用户无需等待正在读相同数据的用户。
保证在并发事务中写数据的用户只需等待正在写相同数据行的用户。
为了维护多版本数据一致性模型,当一个表的数据被更新(写)的同时也在被查询(读)时,Oracle 必须创建一个维持读完整性的数据集。当更新发生时,被更新数据的原始值被记录在数据库的undo records 中。在事务中的更新操作没有被提交之前,用户查询正在被修改的记录时只能看到她们的原始值。Oracle 结合SGA 中以及撤销记录中的信息为查询表数据的用户构建了一个 维持读完整性的视图。
当事务提交后,事务中对数据的修改才被永久记录。在用户事务提交后执行的语句九只能查询到提交后的数据了。
默认情况下,Oracle 只保证语句级的读完整性。由一个查询返回的数据对同一时间点来说是一致的。但是在有些情况下,用户可能需要事务级的读完整性。也就是要使一个事务中的多个查询对同一时间点来说都是一致的,这样事务中的每个查询都不会受到与之冲突的事务的干扰。如果用户需要对多个表做多个查询,建议使用只读事务。
转载:http://www.cnblogs.com/haibin168/archive/2010/12/16/1907407.html
一致性读是oracle区别于其他数据库的重要特点之一,但一般来说,这个一致性读是sql级别的,只针对单个sql有效。
由于业务逻辑需要,我们可能需要在一个事务中的多个sql也能实现读一致性,也就是说,数据源在事务开始时就定下来了,不受其他会话影响。oracle的只读事务可以实现这个功能,它可以在事务级别上实现读一致性。
看下面的实验:
SQL> select * from t1;
ID
---------------------------------------
1
SQL> set serverout on
SQL>
SQL> create or replace procedure p_test is
2 l_id int;
3 begin
4 select id into l_id from t1;
5 dbms_output.put_line(l_id);
6 dbms_lock.sleep(15);
7 select id into l_id from t1;
8 dbms_output.put_line(l_id);
9 end p_test;
10 /
Procedure created
SQL> exec p_test;
--在p_test运行期间(执行dbms_lock.sleep时),修改t1的数据:
SQL> update t1 set id=2;
1 row updated
SQL> commit;
Commit complete
--以下是输出结果
1
2
可以看到,由于第二次读取t1表的数据时,由于有其他会话修改并提交了t1表的数据,所以第二次得到的结果是2.
我们对这个p_test做一个简单的修改,设置只读事务:
SQL> create or replace procedure p_test is
2 l_id int;
3 begin
4 set transaction read only;
5 select id into l_id from t1;
6 dbms_output.put_line(l_id);
7 dbms_lock.sleep(15);
8 select id into l_id from t1;
9 dbms_output.put_line(l_id);
10 end p_test;
11 /
Procedure created
SQL> exec p_test;
--在p_test运行期间(执行dbms_lock.sleep时),修改t1的数据:
SQL> update t1 set id=3;
1 row updated
SQL> commit;
Commit complete
--以下是输出结果
2
2
可以看到,虽然第二次读取t1表的数据前,已经有其他会话修改并提交了t1表的数据,但第二次得到的结果仍然是2.
这就是只读事务的功能,它在整个事务中保证一致性读:在整个事务中的数据在事务开始时就决定,即使有其他会话在事务周期内修改并提交数据,也不会影响事务。可以认为在只读事务周期内,其他事务的对数据的改变就像不存在一样。
在显式提交或者回滚后、或执行ddl后,结束只读事务。
需要注意:因为只读事务的原理是读取undo中数据的前镜像来实现一致性读的,所以,只读事务运行时间不能过长,否则会报0ra-01555。
还有一点,只读事务下是不能对数据做修改的:
suk@ORA10G> set transaction read only;
事务处理集。
suk@ORA10G> delete from test;
delete from test
*
第 1 行出现错误:
ORA-01456: 不能在 READ ONLY 事务处理中执行插入/删除/更新操作