IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

怪异ORA-01502,创建唯一约束却无唯一索引

ilonng 2009-10-12 10:11:17 累计浏览 2,023 次
本机暂存

    我们都知道,唯一约束是基于唯一索引的,如果没有唯一索引,那么在建立唯一约束的时候会自动创建相应的唯一索引。而今天我在创建唯一约束以后,发生了一件怪异的事情。

    下面是过程描述。
因业务要求,要求在一表(test)上一列增加一个唯一约束,由于是在开发环境,数据量也很小,我采用了如下的方法来创建:
SQL> alter table test
  2    add constraint UK_ET_AIRSUP_USERS_supp_WW unique (air_supply_wangwang)
  3    using index
  4    tablespace TBS_ET_IND
  5    online
  6    compute statistics;

    Table altered.

    理论上按照这种方式,已经完全完成工作了。可是,后来测试人员测试的是,却告诉我发生了如下错误:
ORA-01502: index \'.\' or partition of such index is in unusable state

    查询错误描述,可以很清楚的发现问题的原因:
[oracle@crmtest worksh]$ oerr ora 01502
01502, 00000, "index \'%s.%s\' or partition of such index is in unusable state"
// MERGE: 1489 RENUMBERED TO 1502
// *Cause: An attempt has been made to access an index or index partition
//         that has been marked unusable by a direct load or by a DDL
//         operation
// *Action: DROP the specified index, or REBUILD the specified index, or
//         REBUILD the unusable index partition

    昨天都是没有问题,因此我就怀疑我今天这个唯一约束出了问题,查询了一下表的index:
SQL> select index_name,index_type,status from user_indexes where table_name = upper(\'test\');

    INDEX_NAME                     INDEX_TYPE                  STATUS
------------------------------ --------------------------- --------
PK_ET_AIRSUPPLY_USERS          NORMAL                      VALID
UK_ET_AIRSUPPLY_USERS_NICK     NORMAL                      VALID

    怪异的时候发生了,怎么没有相应的唯一索引呢?确定看看唯一约束有没有什么问题:
SQL> alter table test
  2  modify constraint UK_ET_AIRSUP_USERS_SUPP_WW enable validate;

    Table altered.

    再看看结果如何:
SQL> select index_name,index_type,status from user_indexes where table_name = upper(\'test\');

    INDEX_NAME                     INDEX_TYPE                  STATUS
------------------------------ --------------------------- --------
PK_ET_AIRSUPPLY_USERS          NORMAL                      VALID
UK_ET_AIRSUPPLY_USERS_NICK     NORMAL                      VALID

    SQL> delete from test t where t.id in (\'1\',\'2\',\'3\')
  2  ;
delete from test t where t.id in (\'1\',\'2\',\'3\')
*
ERROR at line 1:
ORA-01502: index \'.\' or partition of such index is in unusable state

    还是不对。于是决定重建这个唯一约束:
SQL> select index_name,index_type,status from user_indexes where table_name = upper(\'test\');

    INDEX_NAME                     INDEX_TYPE                  STATUS
------------------------------ --------------------------- --------
PK_ET_AIRSUPPLY_USERS          NORMAL                      VALID
UK_ET_AIRSUPPLY_USERS_NICK     NORMAL                      VALID

    SQL> alter table test
  2  drop constraint UK_ET_AIRSUP_USERS_SUPP_WW;

    Table altered.

    SQL> select index_name,index_type,status from user_indexes where table_name = upper(\'test\');

    INDEX_NAME                     INDEX_TYPE                  STATUS
------------------------------ --------------------------- --------
PK_ET_AIRSUPPLY_USERS          NORMAL                      VALID
UK_ET_AIRSUPPLY_USERS_NICK     NORMAL                      VALID

    SQL> delete from test t where t.id in (\'1\',\'2\',\'3\');

    0 rows deleted.

    SQL> alter table test
  2    add constraint UK_ET_AIRSUP_USERS_supp_WW unique (air_supply_wangwang)
  3    using index
  4    tablespace TBS_ET_IND
  5    online
  6    compute statistics;

    Table altered.

    SQL> delete from test t where t.id in (\'1\',\'2\',\'3\');

    0 rows deleted.

    SQL> rollback;

    Rollback complete.

    SQL> select index_name,index_type,status from user_indexes where table_name = upper(\'test\');

    INDEX_NAME                     INDEX_TYPE                  STATUS
------------------------------ --------------------------- --------
PK_ET_AIRSUPPLY_USERS          NORMAL                      VALID
UK_ET_AIRSUPPLY_USERS_NICK     NORMAL                      VALID
UK_ET_AIRSUP_USERS_SUPP_WW     NORMAL                      VALID

    
SQL> select * from v$version;

    BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.6.0 - Production
PL/SQL Release 9.2.0.6.0 - Production
CORE    9.2.0.6.0       Production
TNS for Linux: Version 9.2.0.6.0 - Production
NLSRTL Version 9.2.0.6.0 - Production
这个时候问题已经解决。但是这个事件有点诡异,这个错误也无法重现,只是想提醒一下,可能会出现这种现象,虽然它几率很小。

    为了避免此类错误的出现,最好的解决方法,至少在生产库上做操作,可以先自己手工创建唯一索引,然后在创建约束,这样就万无一失了。

同分类推荐文章

  1. 使用deepseek进行Oracle恢复,引起重大故障 (2026-06-22 10:56:00)
  2. 接手一个只差临门一脚的数据库恢复 (2026-06-18 00:13:09)
  3. 我做了一个 AI 版的 StarRocks 升级风险扫描工具,直接帮我定位到一个风险 (2026-06-15 01:00:00)

查看更多 数据库 文章 →

建议继续学习

  1. MySQL数据库在实际应用一些方面的介绍 (累计阅读 36,397)
  2. 由浅入深探究mysql索引结构原理、性能分析与优化 (累计阅读 16,523)
  3. 如何查找消耗资源较大的SQL (累计阅读 15,210)
  4. Oracle MTS模式下 进程地址与会话信息 (累计阅读 14,408)
  5. 浅谈MySQL索引背后的数据结构及算法 (累计阅读 11,904)
  6. 其实,文件也可以truncate (累计阅读 8,574)
  7. MariaDB常见问题FAQ (累计阅读 8,344)
  8. SQL vs NoSQL:数据库并发写入性能比拼 (累计阅读 8,003)
  9. Mysql的随机读取 (累计阅读 7,863)
  10. 索引与优化like查询 (累计阅读 7,337)