1。使用一个很小的undo tablespace,并且固定大小
create undo tablespace undo_small datafile 'xxx' size 1m autoextend off;
alter system set undo_tablespace=undo_small scope=memory;
2。建立表,确保数据object_id随机分布
create table t as select * from all_objects order by dbms_random.random;
create index idx_t on t(object_id);
3。在session 1里面进行一个loop的commit操作,这个操作将很快reuse undo block
DECLARE
BEGIN
FOR x IN (SELECT ROWID rid FROM t) LOOP
UPDATE t SET t.object_name=lower(t.object_name) WHERE t.ROWID=x.rid;
COMMIT;
END LOOP;
END;
4。在session 2里面进行查询(强制使用索引,造成random访问)
DECLARE
v t.object_name%TYPE;
CURSOR c IS SELECT /*+ first_rows */ object_name FROM t ORDER BY t.object_id;
BEGIN
OPEN c;
LOOP
FETCH c INTO v;
EXIT WHEN c%NOTFOUND;
dbms_lock.sleep(0.01);
END LOOP;
CLOSE c;
END;
结果分析:
1。当cursor在时间点T1被打开的时候,就决定了数据的读一致性(测试如下)
2。s2读取被s1修改过的数据d1时,需要从undo里面获得T1时刻的d1前镜象数据
3。因为undo很小,undo中存放d1前镜象的block已经被reuse,所以ORA-01555