1、环境:
OS:WINDOWS SERVER 2003
ORACLE:9201
2、现象:
报表开发人员报怨涉及到lothistory表的SQL语句查询巨慢无比:
查看了一下v$session_wait出现了大量的全表扫描(db file scattered read)等待.
lothistory是个大表并且已经按照eventtime做了范围分区.有上亿条记录,没什么说的了,创建索引是必然的了.
综合一下开发人员提供的那些报表SQL,决定创建如下LOCAL索引:
SQL> CREATE INDEX lothistory_idx1 ON lothistory (eventname,areaname,reasoncode,productspecname,oldprocessoperationname,eventtime) LOCAL
(
PARTITION LOTHISTORY08Q4 TABLESPACE LOTHISTORY_IDX08Q4,
PARTITION LOTHISTORY09Q1 TABLESPACE LOTHISTORY_IDX09Q1,
PARTITION LOTHISTORY09Q2 TABLESPACE LOTHISTORY_IDX09Q2,
PARTITION LOTHISTORY09Q3 TABLESPACE LOTHISTORY_IDX09Q3,
PARTITION LOTHISTORY09Q4 TABLESPACE LOTHISTORY_IDX09Q4,
PARTITION LOTHISTORY10Q1 TABLESPACE LOTHISTORY_IDX10Q1
);
此语句运行了一段时间后.就出现了如下错误:
ORA-00603: ORACLE server session terminated by fatal error
3、分析:
看一下数据库后台到底是报了哪样的错误吧:
Errors in file i:\oracle\admin\q1spc01\udump\q1spc01_ora_4028.trc:
ORA-00603: ORACLE server session terminated by fatal error
ORA-01114: IO error writing block to file 201 (block # 523913)
ORA-27069: skgfdisp: attempt to do I/O beyond the range of the file
OSD-04026: 传递的参数无效。 (OS 523943)
ORA-01114: IO error writing block to file 201 (block # 523913)
ORA-27069: skgfdisp: attempt to do I/O beyond the range of the file
OSD-04026: 传递的参数无效。 (OS 523943)
ORA-01114: IO error writing block to file 201 (block # 523913)
ORA-27069: skgfdisp: attempt to do I/O beyond the range of the file
OSD-04026: 传递的参数无效。 (OS 523943)
ORA-01114: IO error writing block to file 201 (block # 523913)
ORA-27069: skgfdisp: attempt to do I/O beyond the range of the file
OSD-04026: 传递的参数无效。 (OS 523943)
那就看看file 201是哪个文件吧:
SQL> select file#,name from v$datafile where file#=201;
未选定行
不是吧?没有?
转了个metalink上的回复。
The file number should appear in v$datafile. If 201 is higher than the number set for db_files, the file is a temp file and you can try the
following:
SELECT name FROM v$tempfile WHERE file#=( - ;
If your DB_FILES parameter is set to 100 within the init.ora and your error shows a problem with file 101, you will know the problem is with
v$tempfile file# = 1.
This appears to be an operating system specific issue. You may be running into a OS file size limitation. You will want to check the event
viewer for further error messages. You should post to the Microsoft Installation/OS: RDBMS for further information as to why this problem is
occuring.
这样就可以找到201这个文件到底是什么了。
SQL> SELECT name FROM v$tempfile WHERE file#=1;
NAME
---------------------------------------------------
I:\ORACLE\ORADATA\Q1SPC01\TEMP01.DBF
竟然是个临时数据文件。
网上找了一下,PUB里就有一个一样的案例(可惜没有具体的解决方案):
http://www.itpub.net/viewthread. ... p;extra=&page=1
主要的说法有:
1):数据文件数量超过了db_files的参数设定值了。(查了一下并没有超出)
SQL> show parameter db_files;
NAME TYPE VALUE
------------------------------------ ----------- -------
db_files integer 200
SQL> select count(*) from v$datafile;
COUNT(*)
----------
51
SQL> select count(*) from v$tempfile;
COUNT(*)
----------
7
2):碰到数据库BUG了。
看了一下TEMP表空间的设置,发现file#=1的数据文件是自动扩展的,并且大小已经达到4GB。其余的都不能自动扩展。
现在意识到问题出在哪了:
可能是因为创建索引时导致tempfile1自动扩展到4GB,达到了操作系统的限制了。
但是比较奇怪的是,当我手动添加新的tempfile以增加TEMP表空间大小后。重新创建索引,问题重现了。
好象写完tempfile1后没办法跳到tempfile2继续写一样。
猜想一下要是不建这么多列的组合索引,只在eventtime一列上创建索引,那用的排序空间应该不会那么大了吧,应该不大于4GB吧,实验一下,真的成功了。
有趣吧?问题肯定就在tempfile1这里了。
4、解决:
问题找到了?如何解决呢?这真是ORACLE的BUG吗?那就升级吧……这是我的第一反应。
等等……
既然问题来自于tempfile的自动扩展至4GB这一操作系统限制,那就在TEMP表空间上面做点文章吧。
相信你也猜到了吧?
我重建一个不可自动扩展TEMP2表空间,然后将系统旧的TEMP表空间切换至TEMP2表空间。这样应该可以了吧?试试吧:
1):查询用户的缺省临时表空间.
SQL> select username,temporary_tablespace from dba_users;
USERNAME TEMPORARY_TABLESPACE
------------------------------ ------------------------------
SYS TEMP
SYSTEM TEMP
DBSNMP TEMP
SPC TEMP
EDU01 TEMP
BI TEMP
SSEXAM TEMP
CTXSYS TEMP
TRAC TEMP
COM TEMP
EC TEMP
USERNAME TEMPORARY_TABLESPACE
------------------------------ ------------------------------
EDU TEMP
OUTLN TEMP
WMSYS TEMP
2):查询现在所用temp的路径.(为切换后的temp做准备)
SQL> select name from v$tempfile;
NAME
-----------------------------------------
I:\ORACLE\ORADATA\Q1SPC01\TEMP01.DBF
I:\ORACLE\ORADATA\Q1SPC01\TEMP02.DBF
I:\ORACLE\ORADATA\Q1SPC01\TEMP03.DBF
I:\ORACLE\ORADATA\Q1SPC01\TEMP04.DBF
I:\ORACLE\ORADATA\Q1SPC01\TEMP05.DBF
I:\ORACLE\ORADATA\Q1SPC01\TEMP06.DBF
I:\ORACLE\ORADATA\Q1SPC01\TEMP07.DBF
3):重建新的临时表空间
create temporary tablespace temp2 tempfile 'I:\ORACLE\ORADATA\Q1SPC01\TEMP2_1.DBF' size 2000M;
alter tablespace temp2 add tempfile 'I:\ORACLE\ORADATA\Q1SPC01\TEMP2_2.DBF' size 2000M;
alter tablespace temp2 add tempfile 'I:\ORACLE\ORADATA\Q1SPC01\TEMP2_3.DBF' size 2000M;
alter tablespace temp2 add tempfile 'I:\ORACLE\ORADATA\Q1SPC01\TEMP2_4.DBF' size 2000M;
4):切换临时表空间.
alter database default temporary tablespace temp2;
select username,temporary_tablespace from dba_users; (查询的结果应和1相同)
SQL> select username,temporary_tablespace from dba_users;
USERNAME TEMPORARY_TABLESPACE
------------------------------ ------------------------------
SYS TEMP2
SYSTEM TEMP2
DBSNMP TEMP2
SPC TEMP2
EDU01 TEMP2
BI TEMP2
SSEXAM TEMP2
CTXSYS TEMP2
TRAC TEMP2
COM TEMP2
EC TEMP2
USERNAME TEMPORARY_TABLESPACE
------------------------------ ------------------------------
EDU TEMP2
OUTLN TEMP2
WMSYS TEMP2
5):确认临时表空间为不可自动扩展模式.
SQL> col file_name for a40
SQL> col tablespace_name for a10
SQL> select file_name,tablespace_name,autoextensible from dba_temp_files;
FILE_NAME TABLESPACE AUT
---------------------------------------- ---------- ---
I:\ORACLE\ORADATA\Q1SPC01\TEMP2_1.DBF TEMP2 NO
I:\ORACLE\ORADATA\Q1SPC01\TEMP2_2.DBF TEMP2 NO
I:\ORACLE\ORADATA\Q1SPC01\TEMP2_3.DBF TEMP2 NO
I:\ORACLE\ORADATA\Q1SPC01\TEMP2_4.DBF TEMP2 NO
6):如果原临时表空间无用户使用,我们可以删除该表空间.
drop tablespace temp;
7):好了,TEMP表空间切换完成了。重新执行一下一开始的创建索引的语句吧。
good!这次成功了。将刚开始创建的那个单列eventtime索引 drop了。
5、总结:
1):TEMP,UNDO表空间最好不要设置成autoextensible,避免带来不必要的麻烦。
2):注意下数据库的小版本号,有机会可以选择升级至更高的小版本。
3):前面猜想的原因可能是因为文件大于4GB受操作系统限制了,可是网上查了一下,ntfs说是单个文件可以支持到64GB的呀,为什么才到4GB就出问题了?
[
本帖最后由 zuohao_lu 于 2009-4-29 16:57 编辑 ]
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12045182/viewspace-592277/,如需转载,请注明出处,否则将追究法律责任。