暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

临时文件和稀疏文件

eygle 2019-10-17
1899

可能有一些朋友也已经注意到,在某些平台下,临时文件的显示大小和实际大小是有区别的。

例如通过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

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论