Home > Database > Mysql Tutorial > ORA-01555模拟与解释

ORA-01555模拟与解释

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
Release: 2016-06-07 17:14:11
Original
1175 people have browsed it

当执行一个查询时间非常长的时候,可能碰到ora-01555错误,本文来模拟并解释一下原因.013555是因为查询的数据在执行查询的过程中,被

当执行一个查询时间非常长的时候,可能碰到ora-01555错误,本文来模拟并解释一下原因.

013555是因为查询的数据在执行查询的过程中,被修改了,同时在undo表空间中已经找不到了造成的.

首先来了解一下Oracle在执行一个查询的时候,在开始查询后其根据条件本该查询出来的数据发生变化的时候,Oracle是将变化之前的数据查询出来的.模拟如下:

1,有一张表的数据如下:

SQL> select *  from A;
        ID VAL
---------- ----------
         1 a
         2 b

2,在一个session(session A)中通过游标查询不open的方式模拟查询开始了,但是还没有真正访问某一条记录:

SQL> variable rc refcursor;
SQL> exec open :rc for select * from A;  --这时候只是表示了开始查询,记录了查询开始的SCN信息等

PL/SQL procedure successfully completed.

3,在另一个session(session B)中修改A表的数据如下并且提交:

SQL> update A set val = 'C';
2 rows updated.
SQL> commit;
Commit complete.

4,在session A中开始访问已经修改并且提交的数据,但是看的数据仍然是查询开始的时间点的数据:

SQL> print rc;
        ID VAL
---------- ----------
         1 a
         2 b

上面的过程是Oracle通过undo表空间中的数据保证的.

那么如果在print rc的时候,undo表空间中对应查询开始时间点的数据不存在了的话,就会01555了.

1,为了模拟这个现象,我们需要让系统使用一个比较小的undo表空间,并且不自动扩展.

create undo tablespace undotbs02 datafile 'D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\UNDOTBS02.DBF' size 1M;
alter system set undo_tablespace=undotbs02

2,在一个session(session A)中通过游标查询不open的方式模拟查询开始了,但是还没有真正访问某一条记录:

SQL> variable rc refcursor;
SQL> exec open :rc for select * from A;  --这时候只是表示了开始查询,记录了查询开始的SCN信息等

PL/SQL procedure successfully completed.

3,在另一个session(session B)中修改A表的数据如下并且提交,通过下面的循环修改造成undo表空间的数据被覆盖:
SQL> declare
  2  i number :=0;
  3  begin
  4  loop
  5  update a set id=i;
  6  i := i+1;
  7  if mod(i,200)=0 then
  8  commit;
  9  end if;
 10  end loop;
 11  end;
 12  /

4,在session A中开始访问已经修改并且提交的数据,发生01555错误

SQL> print rc;
ERROR:
ORA-01555: snapshot too old: rollback segment number 16 with name "_SYSSMU16$"
too small

*最好在执行循环更新的那个session中开始的时候通过 select distinct sid from v$mystat;把sid记下来,最后通过alter system kill session '$sid,$serial#' 杀死那个session,
如果万一没有最先记录下来也可以通过select * from v$locked_object看出那个循环更新的session.

另外,改变了但是没有提交的数据是必须放在undo表空间的,如果undo表空间不够用,会发生ORA-30036错误.还是在undo表空间只有1M的情况下做下面的实验:

SQL> select count(*) from A;

  COUNT(*)
----------
     20008

SQL> delete from A;
delete from A
            *
ERROR at line 1:
ORA-30036: unable to extend segment by 8 in undo tablespace 'UNDOTBS02'

将undo表空间改为一个有比较大的size的datafile的表空间则可以正常delete.

更多Oracle相关信息见Oracle 专题页面 ?tid=12

linux

Related labels:
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template