可能有一些朋友也已经注意到,在某些平台下,临时文件的显示大小和实际大小是有区别的。
例如通过ls –l 查看文件大小得到如下信息:
# cd /md/md1/oracle/proddata # ls -l temp01.dbf -rw-r----- 1 oracle dba 14050926592 8月 16 01:24 temp01.dbf
这里显示临时文件有大约13G大小,而通过du –sk得出的实际大小却只有250M左右:
# du -sk temp01.dbf 267176 temp01.dbf
实际上这是Linux/Unix的一个特性,叫做稀疏文件,Oracle的临时表空间,初始创建时,比如指定14G,这个空间是延后分配的。
只是文件创建时,file header/inode信息记录了这个大小,ls信息来自于此,而du 看的大小是计算实际使用的空间,所以两者会显示不同的结果。
通过稀疏文件,Oracle可以快速创建临时表空间,但是同时也存在隐患,那就是如果将来文件使用时分配空间,而空间不足时将会出现错误。
如果创建时希望分配确定的空间,可以通过创建->删除临时表空间->通过cp复制文件(在Linux需要指定sparse参数,空间将一次分配)->再次创建表空间指定reuse子句使用复制的文件,此时Oracle将可以拥有一个具有指定大小的临时表空间。
例如在Linux上,这个步骤应该大致如下:
SQL> create temporary tablespace temp2 tempfile '/opt/oracle/oradata/eygle/temp2.db' size 10M; Tablespace created. SQL> ! ls -l /opt/oracle/oradata/eygle/temp2.db -rw-r----- 1 oracle dba 10493952 May 29 09:32 /opt/oracle/oradata/eygle/temp2.db SQL> ! du -sk /opt/oracle/oradata/eygle/temp2.db 76 /opt/oracle/oradata/eygle/temp2.db SQL> drop tablespace temp2; Tablespace dropped. SQL> ! cp --sparse=never /opt/oracle/oradata/eygle/temp2.db /opt/oracle/oradata/eygle/temp2.dbf SQL> ! du -sk /opt/oracle/oradata/eygle/temp2.dbf 10264 /opt/oracle/oradata/eygle/temp2.dbf SQL> create temporary tablespace temp2 tempfile '/opt/oracle/oradata/eygle/temp2.dbf' size 10M reuse; Tablespace created. SQL> ! du -sk /opt/oracle/oradata/eygle/temp2.dbf 10264 /opt/oracle/oradata/eygle/temp2.dbf
而在Solaris上,执行cp时我们并不需要添加sparse参数:
$ cp /data1/oradata/systemfile/temp0.dbf /data1/oradata/systemfile/temp0.dbf.2 $ du -sk /data1/oradata/systemfile/temp0.dbf.2 5136 /data1/oradata/systemfile/temp0.dbf.2 $ du -sk /data1/oradata/systemfile/temp0.dbf 88 /data1/oradata/systemfile/temp0.dbf
在Solaris上,可以使用mkfile命令加上-n参数创建sparse文件,我们可以通过Solaris上的测试来看一下稀疏文件在操作系统上的实现。首先创建一个稀疏文件:
# mkfile -n 2m eygle.dbf # ls -l eygle.dbf -rw------T 1 root dba 2097152 Aug 17 22:00 eygle.dbf # du -sk eygle.dbf 16 eygle.dbf
我们注意到,这个2M的稀疏文件只真正占用了16k的空间。借助一个Solaris上的增强工具filestat(这个工具并非系统自带),我们可以发现,Solaris对于这个稀疏文件共分配了32个512bytes的Block(0->15,7280->7295),也就是共16k大小。而其他extent都指向0-15,虽然extent map分配了,但是空间映像就只有32个device block,ls从inode看稀疏文件就得到了"虚假"的大小,而du -sk需要实际检查空间使用就能给出真正的空间占用。
我们通过filestat工具看一下文件空间的分配情况:
# filestat eygle.dbf Inodes per cyl group: 6016 Inodes per block: 64 Cylinder Group no: 0 Cylinder Group blk: 64 File System Block Size: 8192 Device block size: 512 Number of device blocks: 32 Start Block End Block Length (Device Blocks) ----------- ----------- ---------------------- 0 -> 15 16 0 -> 15 16 0 -> 15 16 0 -> 15 16 0 -> 15 16 0 -> 15 16 0 -> 15 16 0 -> 15 16 0 -> 15 16 0 -> 15 16 0 -> 15 16 0 -> 15 16 7280 -> 7295 16 0 -> 15 16 0 -> 15 16 <ignore lots of rows here….> Number of extents: 256 Average extent size: 0 Blocks
而经过cp以后,我们看到,空间立即分配,在Solaris下cp不会考虑稀疏文件,而GNU的Linux下CP命令具有天生的免疫力,可以识别稀疏文件。
# cp eygle.dbf eygle.dbf.bak # ls -l eygle* -rw------T 1 root dba 2097152 Aug 17 22:00 eygle.dbf -rw------- 1 root dba 2097152 Aug 17 22:02 eygle.dbf.bak # du -sk eygle* 16 eygle.dbf 2056 eygle.dbf.bak
这个拷贝的文件真正的分配了使用空间:
# filestat eygle.dbf.bak Inodes per cyl group: 6016 Inodes per block: 64 Cylinder Group no: 0 Cylinder Group blk: 64 File System Block Size: 8192 Device block size: 512 Number of device blocks: 4112 Start Block End Block Length (Device Blocks) ----------- ----------- ---------------------- 7312 -> 7423 112 8304 -> 8383 80 8992 -> 9327 336 1616 -> 1695 80 8384 -> 8479 96 35248 -> 36623 1376 36640 -> 36703 64 36720 -> 37231 512 37632 -> 39071 1440 Number of extents: 9 Average extent size: 456 Blocks
对于Windows操作系统,NTFS从版本5开始支持稀疏文件。可以使用fsutil工具验证Windows是否支持稀疏文件:
C:\>fsutil fsinfo volumeinfo c:\ 卷名 : SYSTEM 卷序列号 : 0x1ce0895c 组件长度最大值 : 255 文件系统名 : NTFS 支持区分大小写的文件名 保留文件名的大小写 支持文件名中的 Unicode 保留并加强 ACL 支持基于文件的压缩 支持磁盘配额 支持稀疏文件 支持重分析点 支持对象标识符 支持加密文件系统 支持带有名称的数据流
尝试在Windows上创建大的临时表空间,可以发现瞬间就完成了创建,这说明创建的同样是稀疏文件:
SQL> create temporary tablespace temp1 tempfile size 1000M; 表空间已创建。 已用时间: 00: 00: 00.41 SQL> select name,bytes/1024/1024/1024 GB from v$tempfile; NAME GB ---------------------------------------------------- ---------- D:\ORADATA\EYGLE\DATAFILE\O1_MF_TEMP_2G8OJPDX_.TMP .01953125 D:\ORADATA\EYGLE\DATAFILE\O1_MF_TEMP1_2T4128L5_.TMP .9765625 已用时间: 00: 00: 00.0