军卫的数据库,大多数是从Oracle7.3 升级到8i,再升级到11G, 在Oracle73时有一个表空间USER_DATA, 一般情况下,多次升级时都会保留下来。
此次在搭建开发数据库时,为给数据库瘦身,需去掉多余的表空间。 在删除USER_DATA表空间前,确保USER_DATA表空间上没有数据库对象。数据库版本为X64-11.2.0.1
一、在下面的操作中,发现了以下的问题:
SQL> show user
USER 为 "SYSTEM"
SQL> select default_tablespace from dba_users where username='SYSTEM';
DEFAULT_TABLESPACE
------------------------------------------------------------
USER_DATA
SQL> CREATE TABLE PBCATFMT
2 (
3 PBF_NAME VARCHAR2(30 BYTE),
4 PBF_FRMT VARCHAR2(254 BYTE),
5 PBF_TYPE INTEGER,
6 PBF_CNTR INTEGER
7 ) ;
CREATE TABLE PBCATFMT
*
ERROR at line 1:
ORA-00959: tablespace 'USER_DATA' does not exist
由于system 用户的缺省表空间是USER_DATA,自然ORA-00959: 错误出现很正常。
SQL> alter user system default tablespace users;
User altered.
SQL> select default_tablespace from dba_users where username='SYSTEM';
DEFAULT_TABLESPACE
------------------------------
USERS
SQL> CREATE TABLE PBCATFMT
2 (
3 PBF_NAME VARCHAR2(30 BYTE),
4 PBF_FRMT VARCHAR2(254 BYTE),
5 PBF_TYPE INTEGER,
6 PBF_CNTR INTEGER
7 ) ;
Table created.
表可以创建成功。
SQL> CREATE INDEX PBSYSCATFRMTS_IDX ON pbcatfmt(pbf_name);
CREATE INDEX PBSYSCATFRMTS_IDX ON pbcatfmt(pbf_name)
*
ERROR at line 1:
ORA-00959: tablespace 'USER_DATA' does not exist
没有指定表空间时,索引创建缺省使用的是创建者的缺省表空间,为什么在这还报错呢?
我重新创建'USER_DATA' 表空间,并重新执行上面的索引创建语句, 自然可以创建成功,查询数据字典,该索引的确也在USERS 表空间上, USER_DATA'表空间上没有数据库对象。
二、原因查找
按照以往的经验,由于这个表是新建的,不存在其它使用USER_DATA 表空间上的触发器或索引。在没有USER_DATA 表空间 的情况下,如果指定表空间,例如 CREATE INDEX PBSYSCATFRMTS_IDX ON pbcatfmt(pbf_name) tablespace users ; 是可以执行成功的。那么数据库后面到底做了些什么?
使用Logminer 对日志进行分析,看看执行创建索引时,数据库到底做了些什么。我们发现,系统对SYS 下的'OBJ$', 'AUD$', 'WRI$_ALERT_THRESHOLD_LOG'和SYSMAN 下的'MGMT_TASK_QTABLE', 'MGMT_COLLECTION_TASKS' 做了操作。会不会这些表使用了USER_DATA 表空间?
SQL> SELECT owner, table_name , tablespace_name
2 FROM dba_tables
3 WHERE ( owner = 'SYS'
4 AND table_name IN ('OBJ$', 'AUD$', 'WRI$_ALERT_THRESHOLD_LOG')
5 )
6 OR ( owner = 'SYSMAN'
7 AND table_name IN ('MGMT_TASK_QTABLE', 'MGMT_COLLECTION_TASKS')
8 );
OWNER TABLE_NAME TABLESPACE_NAME
---------- ------------------------------ --------------------
SYSMAN MGMT_TASK_QTABLE SYSAUX
SYSMAN MGMT_COLLECTION_TASKS SYSAUX
SYS WRI$_ALERT_THRESHOLD_LOG SYSTEM
SYS OBJ$ SYSTEM
SYS AUD$ SYSTEM
可以看到这些表没有使用USER_DATA 表空间。
出于好奇,我又查看了SYS 和SYSMAN 用户缺省表空间的信息:
SQL> SELECT username, default_tablespace, temporary_tablespace
2 FROM dba_users
3 WHERE username IN ('SYS', 'SYSMAN');
USERNAME DEFAULT_TABLESPACE TEMPORARY_TABLESPACE
-------------------- -------------------- --------------------
SYS USER_DATA TEMP
SYSMAN SYSAUX TEMP
发现SYS 缺省的表空间为USER_DATA 。
我试着修改下SYS 缺省的表空间:
SQL> alter user sys default tablespace users;
User altered
再重新创建索引:
SQL> CREATE INDEX PBSYSCATFRMTS_IDX ON pbcatfmt(pbf_name);
Index created
成功!
三、原因猜想
在创建索引时,如果不指定表空间,ORACLE 的某些系统操作会使用SYS 的缺省表空间,而且也许这些操作并不体现在Redo 文件中。因此报ORA-00959 ,不只是看操作数据库用户的信息,也要留意下SYS 用户的信息。