一、 问题背景
昨晚我们在数据库执行以下命令创建了一个索引
create index MYUSER.IDX_MYTABLE_n2 on MYUSER.MYTABLE("updated_at") online;
建完之后开发却反馈MYTABLE表无法插入,插入遇到大量 ORA-08102: index key not found, obj# 55304, file 26, block 1044143 报错,另外在alert日志中还发现在创建IDX_MYTABLE_n2索引时有 ORA-12012: error on auto execute of job "SYS"."CLEANUP_ONLINE_IND_BUILD" 报错。
二、 解决方法
解决方法不复杂,rebuild索引或者删除重建一般就可以。
alter index MYUSER.IDX_MYTABLE_n2 rebuild online; -- 记得要用rebuild online,它会重新读表来创建索引,而rebuild可能会读取原先的索引段而不会去读表。注意这时千万不要人为终止,否则会遇到ora-08104
或者
drop index MYUSER.IDX_MYTABLE_n2;
create index MYUSER.IDX_MYTABLE_n2 on MYUSER.MYTABLE("updated_at") online;
或者(下面这个方法没实际试过)
analyze table MYUSER.MYTABLE validate structure cascade; -- 检查表里的行数据的完全性,并检查表或者索引的结构,并把分析过的结果写入INDEX_STATS 数据字典中
在我们的环境中rebuild索引后恢复了,但还是很好奇 CLEANUP_ONLINE_IND_BUILD 这个job与索引损坏是否有关系。
三、 继续分析
根据DDL审计日志中索引的创建时间和创建索引的同事反馈,可以知道在online创建该索引时CLEANUP_ONLINE_IND_BUILD恰好也在运行。
trace中报错信息如下:
# trace日志
cat /data/prd/oracle/diag/rdbms/orcl/orcl_1/trace/orcl_1_j000_25115.trc
...
Unix process pid: 25115, image: oracle@ORCL-OELDB-cwP01 (J000)
*** 2019-05-08 21:16:27.773
*** SESSION ID:(353.1618) 2019-05-08 21:16:27.773
*** CLIENT ID:() 2019-05-08 21:16:27.773
*** SERVICE NAME:(SYS$USERS) 2019-05-08 21:16:27.773
*** MODULE NAME:(DBMS_SCHEDULER) 2019-05-08 21:16:27.773
*** CLIENT DRIVER:() 2019-05-08 21:16:27.773
*** ACTION NAME:(CLEANUP_ONLINE_IND_BUILD) 2019-05-08 21:16:27.773
online index (re)build cleanup: objn=55304 maxretry=2000 forever=0
*** 2019-05-08 21:16:27.860
ORA-12012: error on auto execute of job "SYS"."CLEANUP_ONLINE_IND_BUILD"
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
ORA-06512: at "SYS.DBMS_PDB", line 76
ORA-06512: at line 4
测试在online创建索引时运行该job,复现了job运行失败的报错,但没有复现索引损坏的报错。
1. Create Index
SQL> create index ind_OBJECT_NAME on test_index(OBJECT_NAME) online;
2. Run CLEANUP_ONLINE_IND_BUILD job when index is creating
SQL> exec dbms_scheduler.run_job('CLEANUP_ONLINE_IND_BUILD');
BEGIN dbms_scheduler.run_job('CLEANUP_ONLINE_IND_BUILD'); END;
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
ORA-06512: at "SYS.DBMS_PDB", line 76
ORA-06512: at line 4
ORA-06512: at "SYS.DBMS_ISCHED", line 209
ORA-06512: at "SYS.DBMS_SCHEDULER", line 594
ORA-06512: at line 1
3. Update and insert test_index table
SQL> insert into test_index select * from test_index where rownum<5;
4 rows created.
SQL> update test_index set OBJECT_NAME='hytest' where OBJECT_NAME='I_USER1';
258 rows updated.
SQL> COMMIT;
Commit complete.
我们找到了一个相关bug的文档,开了一个SR,不过SR反馈并非由该bug导致。
Bug 21532755 - ORA-600 [25027] By Concurrent queries while Create Index Online or ORA-8102 Table/Index mistmatch after Create Index Online or ONLINE_INDEX_CLEAN wait for DMLs (文档 ID 21532755.8)
SR认为这个应该是已知问题而不是bug,建议参考文档
ORA-8102 CORRUPT INDEX, ORA-1499 EVEN AFTER DROPPING AND RECREATING INDEX ( Doc ID 1081343.6 )
ORA-54 Error On Auto Execute Of Job "SYS"."CLEANUP_ONLINE_IND_BUILD" ( Doc ID 2280374.1 )
但感觉SR的回复只解答了CLEANUP_ONLINE_IND_BUILD job 运行失败的原因,没能给我们找到ORA-8102的原因。目前应该只能说在online创建索引时运行CLEANUP_ONLINE_IND_BUILD job会导致job运行失败,但不能说该job运行会导致索引损坏。