在大型OLAP系统中运行查询经常会遭遇“ORA-01555: snapshot too old”的错误。这是因为Oracle为了保持读一致性,需要从回滚段中读取被修改的记录,但是同时这条被修改的记录在回滚段中却找不到了。这时,就会报错“ORA-01555: snapshot too old”。实验思路:
1. 创建大小为1M的回滚段,并让系统指定使用它。
2. 创建一个游标cur,让它查询表TA,但是先不打印,如下的session_1_test3。
3. 更新表TA中的第二行,并且提交,如下的session_2_test3。
4. 刷新SGA中的高速数据缓存,使得回滚段空间全部为可用,如下的session_3_sysdba。
5. 频繁的更新某一个表,确保回滚段中的空间全部被覆盖,意即找不到步骤3中被更新的记录,如下的session_4_test3。
6. 在步骤2中的session中打印游标cur。
步骤1
- SQL> conn / as sysdba;
- 已连接。
- SQL> create undo tablespace UNDOTBS4 datafile 'D:\ORACLE TABLESPACES\UNDOTBS04_1.DBF' size 1M autoextend off;
- Tablespace created
- SQL> alter system set undo_tablespace = UNDOTBS4 scope = both;
- System altered
- SQL> alter system set undo_retention=1 scope = both;
- System altered
- SQL> column name format a20
- SQL> column display_value format a20
- SQL> select name, display_value from v$parameter where name like 'undo%';
- NAME DISPLAY_VALUE
- -------------------- --------------------
- undo_management AUTO
- undo_tablespace UNDOTBS4
- undo_retention 1
- SQL> select tablespace_name, RETENTION from dba_tablespaces where tablespace_name = 'UNDOTBS4';
- TABLESPACE_NAME RETENTION
- ------------------------------ -----------
- UNDOTBS4 NOGUARANTEE
- SQL> create user test3 identified by test3;
- User created
- SQL> grant connect, resource to test3;
- Grant succeeded
- SQL>
步骤2
- SQL> conn test3/test3;
- 已连接。
- SQL> set sqlprompt 'session_1_test3> ';
- session_1_test3> create table TA (a number, b varchar2(20));
- 表已创建。
- session_1_test3> insert into TA (a, b) values(1, 'a');
- 已创建 1 行。
- session_1_test3> insert into TA (a, b) values(2, 'b');
- 已创建 1 行。
- session_1_test3> commit;
- 提交完成。
- session_1_test3> var cur refcursor;
- session_1_test3> begin
- 2 open :cur for select * from TA;
- 3 end;
- 4 /
- PL/SQL 过程已成功完成。
- session_1_test3>
步骤3
- SQL> conn test3/test3
- 已连接。
- SQL> set sqlprompt 'session_2_test3';
- session_2_test3> update TA set b = 'c' where a = 2;
- 已更新 1 行。
- session_2_test3> commit;
- 提交完成。
- session_2_test3>
步骤4
- SQL> conn / as sysdba
- 已连接。
- SQL> set sqlprompt 'session_3_sysdba >';
- session_3_sysdba >--The FLUSH BUFFER_CACHE clause lets you clear all data from the buffer cache in the system global area (SGA).
- session_3_sysdba >alter system flush buffer_cache;
- 系统已更改。
- session_3_sysdba >
步骤5
- session_4_test3> create table testa as select * from dual;
- 表已创建。
- session_4_test3> begin
- 2 for i in 1..10000 loop
- 3 update testa set dummy = 'A';
- 4 commit;
- 5 end loop;
- 6 end;
- 7 /
- PL/SQL 过程已成功完成。
- session_4_test3>
步骤6
- session_1_test3> print cur;
- ERROR:
- ORA-01555: 快照过旧: 回退段号 29 (名称为 "_SYSSMU29$") 过小
- 未选定行
- session_1_test3>
备注:
ORA-01555: snapshot too old: rollback segment number string with name "string" too small
Cause: rollback records needed by a reader for consistent read are overwritten by other writers
Action: If in Automatic Undo Management mode, increase undo_retention setting. Otherwise, use larger rollback segments
转载于:https://blog.51cto.com/tianyu1102/557779