一条TRUNCATE命令所带来的严重后果
上午有同事让我帮他删除数据,因为他用DELETE删除时很慢,就把删除语句发给我了:
DELETE FROM cjcl.cj_cj_tbjd where bgq = '201309MM'
我一看,这条语句所删除的内容正是某个分区的数据:
SELECT COUNT(0) FROM cjcl.cj_cj_tbjd where bgq = '201308MM'; --RWID_601_BGQ_201309MM
SELECT COUNT(0) FROM cjcl.cj_cj_tbjd SUBPARTITION (RWID_601_BGQ_201308MM)
执行上面两条命令,所得的结果都一样,可以肯定要删除的数据全在这个分区上,于是就用下面的命令来删除数据:
ALTER TABLE cjcl.cj_cj_tbjd TRUNCATE SUBPARTITION RWID_601_BGQ_201309MM
删除是很快的,可没过多长时间,应用那边的人就找麻烦了,发来了一条错误消息:
DELETE FROM CJCL.CJ_CJ_SJXGJL WHERE REPORTID = '5EB74170' AND BGQ = '201301YY' AND DCDXXTM = '0316344']; SQL state [null]; error code [17081]; 批处理中出现错误: ORA-01502: 索引 'CJCL.PK_CJ_CJ_TBJD' 或这类索引的分区处于不可用状态
错误消息主要是后面"ORA-01502: 索引 'CJCL.PK_CJ_CJ_TBJD' 或这类索引的分区处于不可用状态",查询了一下这个索引,原来是被删除数据的那张表的主键全局索引,这下可好了,由于刚才执行的TRUNCATE(DDL)命令,使这张表的主键全局分区索引失效,再对这张表进行更新或插入操作的时候,就直接报上面的错误了,这张表很大,有1亿100万行数据,现在也没办法了,只能把这张表的这个索引REBUILD一下,于是后来执行了下面的命令对这个索引进行REBUILD:
ALTER INDEX PK_CJ_CJ_TBJD REBUILD PARALLEL 10; // 一 刚开始没有使用并行,非常慢,跑了3个小时也没有跑出来,于是终止了,并加了并行。
当这个主键全局分区索引执行完成后,一切才慢慢才恢复正常,过程从下午4点折腾到晚上9点才结束。
总结:如果一张表是分区表,并且这张表上有全局分区索引,则千万不要用TRUNCATE 及类似的DDL来操作这张表,这样会导致全局分区索引失效,从而使应用挂住,无法在这张表上进行DML操作,就如同上面的删除操作,如果用DELETE来删除数据,这个问题就不会发生了。