今天给临时表空间增加临时文件(size 4G)的时候,发现速度极快完成。
然后进入文件系统发现 ls 可以看到文件尺寸的大小。但是du -g 发现空间并没有分配。
v$tempfile 和dba_temp_files 都能查询到新增的文件。所以考虑到应该是oracle 预分配空间,但是不真实的分配
eygle 说:http://www.eygle.com/archives/2005/08/unix_sparse_fil.html
实际上这是Unix/Linux的一个特性,Oracle的临时表空间,初始创建时,比如你指定14G,这个空间是延后分配的。
只是文件创建时,file header/inode信息记录了这个大小,ls信息来自于此,而du 看的大小是计算实际使用的空间,所以可能不同于ls的结果。
而一旦你copy复制出来,空间必须立即分配,就是你你创建临时表空间/扩展的大小。
当然我们备份时是完全可以不备份临时表空间的。
这个特性在Unix/Linux上称为:Sparse File(稀疏文件)。
对于Windows操作系统,大部分(较新)版本同样支持稀疏文件。可以使用fsutil工具验证Windows是否支持稀疏文件:
C:\>fsutil fsinfo volumeinfo c:\
卷名 : SYSTEM
卷序列号 : 0×1ce0895c
组件长度最大值 : 255
文件系统名 : NTFS
支持区分大小写的文件名
保留文件名的大小写
支持文件名中的 Unicode
保留并加强 ACL
支持基于文件的压缩
支持磁盘配额
支持稀疏文件
支持重分析点
支持对象标识符
支持加密文件系统
支持带有名称的数据流
通过稀疏文件,Oracle可以快速创建临时表空间,但是同时也存在隐患,那就是如果将来文件使用时分配空间,而空间不足时将会出现错误。
如果创建时希望分配确定的空间,可以通过创建->删除表空间->再次创建制定reuse子句,此时Oracle将按指定大小一次分配存储空间。
在Solaris上,可以使用mkfile命令加上-n参数创建sparse文件:
NAME mkfile - create a fileSYNOPSIS
mkfile [ -nv ] size [ k | b | m ] filename …DESCRIPTION
mkfile creates one or more files that are suitable for use
as NFS-mounted swap areas, or as local swap areas. When a
root user executes mkfile(), the sticky bit is set and the
file is padded with zeros by default. When non-root users
execute mkfile(), they must manually set the sticky bit
using chmod(1). The default size is in bytes, but it can be
flagged as kilobytes, blocks, or megabytes, with the k, b,
or m suffixes, respectively.OPTIONS
-n Create an empty filename. The size is noted, but disk
blocks are not allocated until data is written to
them. Files created with this option cannot be swapped
over local UFS mounts.
简单测试如下:
$ df -k /export/home
Filesystem kbytes used avail capacity Mounted on
/dev/dsk/c1t0d0s7 8263373 6682413 1498327 82% /export/home
$ pwd
/export/home/gqgai
$ mkfile -n 2000m sparsefile.dbf
$ ls -l sparsefile.dbf
-rw——- 1 gqgai maintain 2097152000 Aug 16 22:31 sparsefile.dbf
$ df -k /export/home
Filesystem kbytes used avail capacity Mounted on
/dev/dsk/c1t0d0s7 8263373 6682437 1498303 82% /export/home
===============================
引用 I Believe 的一篇文章 http://oract.itpub.net/post/19116/406706
SQL> alter tablespace temp add tempfile ‘/oradata/test/temp03.dbf’ size 100M autoextend off;
Tablespace altered.
SQL> exit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
[oracle@testsvr test]$ ls -l
total 1898376
-rw-r–r– 1 oracle oinstall 89 Oct 19 14:56 afiedt.buf
drwxr-xr-x 2 oracle oinstall 4096 Aug 28 16:05 bak
-rw-r—– 1 oracle oinstall 10076160 Oct 19 14:57 control01.ctl
-rw-r—– 1 oracle oinstall 10076160 Oct 19 14:57 control02.ctl
-rw-r—– 1 oracle oinstall 10076160 Oct 19 14:57 control03.ctl
-rw-r—– 1 oracle oinstall 882778112 Oct 19 14:57 sysaux01.dbf
-rw-r—– 1 oracle oinstall 734011392 Oct 19 14:56 system01.dbf
-rw-r—– 1 oracle oinstall 104865792 Oct 19 10:10 temp01.dbf
-rw-r—– 1 oracle oinstall 104865792 Oct 8 15:19 temp02.dbf
-rw-r—– 1 oracle oinstall 104865792 Oct 19 14:57 temp03.dbf
-rw-r–r– 1 oracle oinstall 3922 Oct 19 14:53 test.log
-rw-r—– 1 oracle oinstall 209723392 Oct 19 14:57 undotbs01.dbf
-rw-r—– 1 oracle oinstall 5251072 Oct 19 02:51 users01.dbf
-rw-r—– 1 oracle oinstall 1056768 Oct 19 14:51 users02.dbf
[oracle@testsvr test]$ od -c ./temp03.dbf > ./temp03.txt
[oracle@testsvr test]$ cat temp03.txt
0000000 242 300 377
0000020 f 310 2 } | { z
0000040 240 201
0000060
*
0020000 v 242 001 300 001 004
0020020 G a 020 v 311 B 371 r
0020040 T E S T < x 2
0020060 003 006
0020100
*
0020140 330 5 344 211 356 %
0020160
*
0020500 003
0020520 004 T E M P
0020540
0020560 003
0020600
*
0037760 001 v
0040000 035 242 002 300 001 001 f
0040020 261 260 003 200 2
0040040 001 a
0040060 210 1 c
0040100
*
0057760 001 035 001
0060000 036 242 003 300 001 001 f
0060020 V 277 003 t 001
0060040 200 017
0060060
*
0077760 001 036 001
0100000 036 242 004 300 001 001 f
0100020 V 177 003 t 300 a 001
0100040 200 017
0100060
*
0117760 001 036 001
0120000 036 242 005 300 001 001 f
0120020 _ ? 003 t 200 017 001
0120040 200 017
0120060
*
0137760 001 036 001
0140000 036 242 006 300 001 001 f
0140020 D 377 003 t @ 027 001
0140040 200 017
0140060
*
0157760 001 036 001
0160000 036 242 a 300 001 001 f
0160020 M 277 003 t 037 001
0160040 200 017
0160060
*
0177760 001 036 001
0200000 036 242 b 300 001 001 f
0200020 { 177 003 t 300 & 001
0200040 200 017
0200060
*
0217760 001 036 001
0220000
*
620020000
[oracle@testsvr test]$
结果证实了temp03.dbf 文件之中从0220000 到620020000 的部分全部是 空洞。
===================================
引用文件空洞的概念: http://blog.chinaunix.net/u2/72383/showart_1432837.html
1. 文件是可以有空洞的,空洞不占用磁盘空间,但是我们用ls查看的文件大小是将空洞算在内的。
2. cp命令拷贝的文件,空洞部分不拷贝,所以生成的文件同样占用磁盘空间小
3. 用read读取空洞部分读出的数据是0,所以如果用read和write拷贝一个有空洞的文件,那么最终得到的文件没有了空洞,空洞部分都被0给填充了,文件占用的磁盘空间就大了。不过文件大小不变。
例子:
$ dd if=/dev/null of=aba bs=1024k seek=5
0+0 records in
0+0 records out
0 bytes transferred in 1 secs (0 bytes/sec)
$ ls -al aba
-rw-r–r– 1 langue universe 5242880 Nov 8 05:50 aba
$ du aba
16 aba
$ cp aba bab
$ du aba bab
16 aba
5128 bab
$ uname -a
NetBSD 1.3 NetBSD 1.3 (GENERIC-O) #344: Thu Oct 29 02:26:40 CST 2006 langue@:usr/src/sys/arch/i386/compile/GENERIC-O i386
$ mount
/dev/wd0a on / type ffs (local)
/dev/wd0e on /usr type ffs (local)
kernfs on /kern type kernfs (local)
使用如下程序进行文件拷贝测试:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#define BUFSIZE 4096
char buf[BUFSIZE] ;
int main(int argc ,char *argv[])
{
int f_src,f_dest;
ssize_t rcount,wcount;
if(argc!=3)
{
printf(”usage:copy filename1 filename2\n”);
return 0;
}
if(strcmp(argv[1],”-”)==0)
f_src=STDIN_FILENO;
else
{
if((f_src=open(argv[1],O_RDONLY))<0)
{
printf(”cant not open %s\n”,argv[1]);
return 0;
}
}
if(strcmp(argv[2],”-”)==0)
f_dest=STDOUT_FILENO;
else
{
umask(0);
if((f_dest=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP))<0)
{
printf(”cant not open %s\n”,argv[2]);
perror(”open failed!!”);
return 0;
}
umask(022);
}
while((rcount=read(f_src,buf,BUFSIZE))>0)
{
if((wcount=write(f_dest,buf,rcount))!=rcount)
{
perror(”write error!!”);
return 0;
}
}
if(rcount<0)
perror(”read error”);
return 0;
}
测试结果:
$ dd if=/dev/null of=tmpfile bs=1024k seek=1
0+0 records in
0+0 records out
0 bytes transferred in 1 secs (0 bytes/sec)
$ ./copy tmpfile tmpfile1
$ du tmp*
32 tmpfile
2064 tmpfile1
$ hexdump tmpfile
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
0100000
$ hexdump tmpfile1
0000000 0000 0000 0000 0000 0000 0000 0000 0000
*
0100000
$
从 tmpfile1 占用了 2064 个 512 字节大小的块可以看出,它的确占用了至少 1024KB,而 tmpfile 只有 16KB,根据 ls -al tmpfile* 的结果:
$ ls -al tmpfile*
-rw-rw-r– 1 langue universe 1048576 Nov 8 13:05 tmpfile
-rw-rw—- 1 langue universe 1048576 Nov 8 13:05 tmpfile1
