在数据库运维的世界里,Oracle数据库一直以其强大的功能和稳定性受到众多企业的青睐。然而,即使是经验丰富的运维人员,在面对 Oracle 11g的某些特性时,也可能会遇到一些小困惑。今天,我们就来聊聊一个让不少初学者头疼的问题——Oracle 11g 空表不导出。
在Oracle 11g的11.2.0.2版本中,出现了一个新特性:表创建时不分配空间,而是在第一次数据插入时才分配空间。这就导致了一个有趣的现象——使用传统的exp工具导出数据库时,那些没有分配空间的空表是不会被导出的。
想象一下,你辛辛苦苦创建了一个表,结果在导出数据库时却发现它不见了,是不是会有点抓狂?别担心,这并不是你的操作有问题,而是Oracle数据库的一个新特性在“作祟”。
关键知识点:deferred_segment_creation 参数
Oracle 11g新增了一个参数——deferred_segment_creation,它的含义是段延迟创建。默认情况下,这个参数的值是true。也就是说,当你新建一个表但没有向其中插入数据时,这个表不会立即分配extent(扩展),也就是不占用数据空间。只有当你插入数据后,才会分配空间。这样做的好处是可以节省少量的空间。
不过,这里有个小例外。如果你是在系统用户(sys用户)下创建表,那么这个参数的影响就会被忽略。无论参数值如何,系统用户下的表在创建时都会分配空间。
解决方法
方法一:修改deferred_segment_creation参数
如果你希望无论是空表还是非空表,都分配segment,那么可以将deferred_segment_creation参数设置为FALSE。具体操作如下:
ALTER
SYSTEM
SET deferred_segment_creation=
FALSE;
查看参数是否修改成功:
show parameter deferred_segment_creation;
或者:
SELECT
name,
TYPE,
VALUE, isses_modifiable, issys_modifiable
FROM v$parameter
WHERE
name
LIKE
'defer%';
需要注意的是,修改这个参数后,它只对后面新增的表产生作用,对之前已经建立的空表是不起作用的。而且,通常情况下,还需要重新启动数据库,让参数真正生效。
方法二:在创建表时指定段创建方式
如果你不想修改系统参数,也可以在创建表的时候直接指定是否创建段。如果你想在创建表的同时创建段,可以使用以下语法:
create
table
test(
id
number(
10))
SEGMENT
CREATION
IMMEDIATE;
相反,如果你想在创建表时不创建段(非sys用户),可以使用:
create
table
test(
id
number(
10))
SEGMENT
CREATION
DEFERRED;
方法三:手动为表分配段
如果你已经创建了空表,并且希望为它们分配段,可以使用以下方法:
BEGIN
DBMS_SPACE_ADMIN.materialize_deferred_segments (
schema_name =>
'SCOTT',
table_name =>
'TEST'
);
END;
/
或者:
ALTER
TABLE TableName
ALLOCATE
EXTENT;
如果是分区表,可以使用:
ALTER
TABLE TableName
modify
partition partition_name
ALLOCATE
EXTENT;
方法四:删除空表的段
如果你想要将空表的段删除,可以执行以下操作:
BEGIN
DBMS_SPACE_ADMIN.drop_empty_segments;
END;
/
方法五:构建对空表分配空间的SQL命令
如果你想批量为当前用户下的所有空表分配空间,可以按照以下步骤操作:
首先,查询当前用户下的所有空表:
SELECT table_name
FROM user_tables
WHERE NUM_ROWS =
0;
然后,构建针对空表分配空间的命令语句:
set echo
off feed
off pages
0
spool temp.sql
SELECT
'alter table ' || table_name ||
' allocate extent;'
FROM user_tables
WHERE num_rows =
0
AND partitioned =
'NO';
SELECT
'alter table '
|| table_name
||
' modify partition '
|| partition_name
||
' allocate extent;'
FROM USER_TAB_PARTITIONS
WHERE num_rows =
0;
spool off
set echo
on feed
on
@ temp.sql
Oracle 11g的空表不导出问题,其实是数据库为了优化空间使用而设计的一个特性。通过了解deferred_segment_creation参数的作用,以及掌握相应的解决方法,你可以轻松应对这个问题。