Portanto, como mencionei antes, sou um DBA/Consultor do SQL Server que está ajudando um cliente com seus bancos de dados Oracle. Principalmente, consegui descobrir o que preciso e resolver as coisas com a ajuda do documento e do Google, mas atualmente estou tentando lidar com algo que parece inescrutável.
Um dos bancos de dados é um banco de dados Oracle 10g LIMS que existe (e atualizado) há pelo menos 10 anos (talvez 20). É um aplicativo crítico, mas eles têm tido vários problemas de confiabilidade com ele nos últimos dois anos. Para tentar entender o que realmente há de errado com ele e o que podemos fazer a respeito, pedimos ao provedor de hospedagem/MS que fizesse uma cópia física dele em outro servidor (idêntico). (Tenho certeza de que o provedor interpretou isso como "backup e restauração do RMAN").
A ideia é que eu poderia fazer qualquer análise, investigação, tentativa de reparo e usar qualquer ferramenta que quisesse sem nenhum perigo de afetar a produção. Até agora tudo bem. Executei DBVerify ( dbv
) em todos os arquivos de dados, sem problemas.
Então corri ANALYZE TABLE .. VALIDATE STRUCTURE CASCADE ONLINE;
em todas as tabelas do banco de dados. Para duas dessas tabelas, o comando demorou muito mais do que as outras 2500 tabelas (combinadas), então as cancelei e deixei as outras terminarem, o que fizeram sem problemas e sem erros relatados, etc.
Essas duas tabelas também são as maiores tabelas de dados de aplicativos. Então eu começo com a maior tabela (23GB, 36M linhas) e decido analisá-la por partes (sem o CASCADE), primeiro a própria tabela e depois os índices. A tabela termina em 30-60 minutos (não me lembro exatamente), mas a ANALYZE INDEX .. VALIDATE STRUCTURE ONLINE;
do primeiro índice nunca termina.
Decidi deixá-lo funcionar por um tempo e ver se encontrava uma maneira de monitorar seu progresso. Pesquisando no Google, encontro muitas reivindicações (antigas) de que ANALYZE TABLE pode ser monitorado v$session_longops
, mas olhando para ele nunca mostrou nada do meu comando e cheguei à conclusão de que isso deve funcionar apenas para a função de coleta de estatísticas, não para a função de validação. Depois de tentar várias coisas, acabei descobrindo que, olhando a v$session
linha do comando em execução, poderia usar as colunas P1* e P2* para rastrear qual arquivo e bloco estava sendo lido.
Isso me mostrou que ele estava realmente lendo os arquivos de dados esperados e estava lendo diferentes blocos deles. Isso e o fato de que a utilização do disco no servidor era de 100% enquanto o comando estava sendo executado (e nada mais) me convenceu de que ele realmente estava fazendo algo e não estava bloqueado/bloqueado/travado. Então eu apenas deixei correr.
Já se passaram mais de 3 dias (+72 horas) e não mostra sinais de terminar e estou meio perdido aqui.
Informação adicional:
DDL da tabela:
-- Unable to render TABLE DDL for object O$LIMS.N__RESULTS with DBMS_METADATA attempting internal generator.
CREATE TABLE O$LIMS.N__RESULTS
(
SAMPLE_ID NUMBER(10, 0) NOT NULL
, SUBMISSION_ID NUMBER(10, 0) NOT NULL
, RESULT_ID NUMBER(10, 0) NOT NULL
, RESULT_VERSION NUMBER(3, 0) NOT NULL
, TASK_ID NUMBER(10, 0) NOT NULL
, TASK_REPETITION NUMBER(3, 0) NOT NULL
, TASK_VERSION NUMBER(3, 0) NOT NULL
, REQUIRED VARCHAR2(1 BYTE) NOT NULL
, METHOD_DATAGROUP VARCHAR2(40 BYTE) NOT NULL
, COMPONENT VARCHAR2(40 BYTE) NOT NULL
, MEASURE VARCHAR2(40 BYTE) NOT NULL
, UNITS VARCHAR2(40 BYTE) NOT NULL
, STATUS VARCHAR2(20 BYTE) NOT NULL
, PLANNED_RESULT VARCHAR2(3 BYTE) NOT NULL
, RESULT_ORIGIN VARCHAR2(1 BYTE) NOT NULL
, CONDITION VARCHAR2(20 BYTE) NOT NULL
, CONDITION_LEVEL VARCHAR2(20 BYTE)
, VALUE_TYPE VARCHAR2(20 BYTE) NOT NULL
, NUMBER_VALUE NUMBER
, TEXT_VALUE VARCHAR2(80 BYTE)
, TIME_VALUE DATE
, REASON VARCHAR2(40 BYTE)
, INLIMIT VARCHAR2(3 BYTE)
, INDETECTION VARCHAR2(3 BYTE)
, INSPEC VARCHAR2(3 BYTE)
, ENTRY_USERID VARCHAR2(20 BYTE)
, ENTRY_DATE DATE
, SPEC_ID NUMBER(10, 0)
, SPEC_VERSION NUMBER(3, 0)
, DETECTION_ID NUMBER(10, 0)
, DETECTION_VERSION NUMBER(3, 0)
, LIMIT_ID NUMBER(10, 0)
, LIMIT_VERSION NUMBER(3, 0)
, CUSTOMER_DATAGROUP VARCHAR2(40 BYTE)
, ANALYST VARCHAR2(20 BYTE)
, REPORT VARCHAR2(3 BYTE)
, TIMESTAMP DATE
, USERSTAMP VARCHAR2(20 BYTE)
, MEASURE_LINK O$LIMS.N_UT_MEASURE
, RESULT_PLAN_LIST_LINK O$LIMS.N_UT_RESULT_PLAN_LIST
, TEXT O$LIMS.N_TT_TEXT
, ATTRIBUTES O$LIMS.N_TT_ATTRIBUTES
, SEQUENCE NUMBER(4, 0)
, CONSTRAINT N_C_RESULTS_1 PRIMARY KEY
(
RESULT_ID
, RESULT_VERSION
)
USING INDEX
(
CREATE UNIQUE INDEX O$LIMS.N_C_RESULTS_1 ON O$LIMS.N__RESULTS (RESULT_ID ASC, RESULT_VERSION ASC)
LOGGING
TABLESPACE "SQLLIMS_INDEX"
PCTFREE 10
INITRANS 2
STORAGE
(
INITIAL 311296
NEXT 1048576
MINEXTENTS 1
MAXEXTENTS UNLIMITED
BUFFER_POOL DEFAULT
)
NOPARALLEL
)
ENABLE
)
LOGGING
TABLESPACE "SQLLIMS_RESULTS"
PCTFREE 25
INITRANS 1
STORAGE
(
INITIAL 566231040
NEXT 1048576
MINEXTENTS 1
MAXEXTENTS UNLIMITED
BUFFER_POOL DEFAULT
)
NOCOMPRESS
NOPARALLEL
NESTED TABLE TEXT STORE AS RESULT_TEXT RETURN AS VALUE
NESTED TABLE ATTRIBUTES STORE AS RESULT_ATTRIBUTES RETURN AS VALUE
O DDL do índice atualmente sendo analisado:
-- Unable to render INDEX DDL for object O$LIMS.SYS_C0010496 with DBMS_METADATA attempting internal generator.
CREATE UNIQUE INDEX O$LIMS.SYS_C0010496 ON O$LIMS.N__RESULTS (ATTRIBUTES ASC)
LOGGING
TABLESPACE "SQLLIMS_RESULTS"
PCTFREE 10
INITRANS 2
STORAGE
(
INITIAL 65536
NEXT 1048576
MINEXTENTS 1
MAXEXTENTS UNLIMITED
BUFFER_POOL DEFAULT
)
NOPARALLEL
Minhas perguntas:
É razoável que o ANALYZE INDEX demore tanto quando o ANALYZE TABLE levou no máximo 1 hora?
Quais são minhas opções neste momento? Supondo que eu elimine isso, como posso prosseguir com a verificação de corrupção (lógica), etc.? Existe algo que eu possa fazer para que esse comando seja concluído em um tempo razoável ou existe alguma outra ferramenta ou abordagem que eu possa usar?
Versão, etc. informações:
- Host: servidor Windows 2003, sp2
- Versão do Oracle: 10g r2 ps3 10.2.0.4.0
- Compatibilidade: 10.2.0.3.0
Aqui estão os parâmetros SGA relevantes (eu acho):
- sga_target: 7012876288 (6688M)
- sga_max_size: 10015997952 (9552M)
- db_block_size: 8192
- db_cache_size: 2885681152 (2752M)
- db_*k_cache_size: todos são zero
ATUALIZAÇÃO: O que funcionou...
Então, depois de ler o link de @Raj e ler a resposta de @ora-600, tentei validar o banco de dados com o comando RMAN
backup check logical validate database;
. Enquanto isso funcionou bem, também ficou claro que não estava olhando para tudo o que oANALYZE INDEX
comando faria.Depois de tentar muitas variações diferentes, finalmente descobri que este comando funcionaria :
Sim, apenas mudar para OFFLINE parece resolver isso. E isso eventualmente me levou a este bug# 5752105 nesta página: http://www.eygle.com/case/10204_buglist.htm . Não estou em posição de provar isso agora (não posso aplicar nenhum patch por enquanto), mas suspeito fortemente que era nisso que eu estava me deparando.
Portanto, embora a pergunta não seja totalmente respondida, vou marcar a resposta muito útil de @ora-600 como correta para que ele possa coletar a generosidade generosa de Paul White.
Acho que o artigo citado por Raj ( https://www.pythian.com/blog/analyze-index-validate-structure-dark-side/ ) descreve isso muito bem. "fator de agrupamento" também foi meu primeiro palpite ao ler a descrição do seu problema. Também prefiro usar o RMAN para verificar se há corrupção.
Depois, você pode consultar
V$DATABASE_BLOCK_CORRUPTION
detalhes sobre qualquer bloco corrompido.Normalmente, há um motivo para agrupamentos enormes. Você pode verificar os seguintes detalhes:
Isso pode ajudá-lo a determinar se o clustering_factor é alto. Você também pode consultar
dba_extents
para determinar o clustering_factor.Por que o cluster é ruim para o desempenho? Quando o Oracle lê dados do disco ou cache, ele sempre lê em bloco. Se o bloco estiver meio vazio, você perde 50% do seu desempenho de leitura. Caso você faça uma varredura completa de tabela ou índice completo, o Oracle verifica todos os blocos pertencentes ao segmento (índice ou tabela). Não verifica se um bloco está vazio ou não. O Oracle lê do primeiro bloco ao último (HWM). Se o seu índice tiver 10mil blocos, mas precisar apenas de 1mil blocos, o Oracle lerá 9mil blocos de lixo.
O ASSM (Automatic Segment Space Management) ajuda muito a reduzir/evitar o agrupamento. Se possível, você deve migrar Tbs gerenciados pelo espaço de segmento manual para ASSM Tbs.
Por que verificar se há corrupção? Sempre começo analisando um banco de dados reunindo relatórios ASM ou statspack do banco de dados de produção (não um banco de dados de teste/desenvolvimento). Isso não machuca ninguém e lhe dará muitos detalhes sobre o banco de dados e seus pequenos segredos. A corrupção geralmente não afeta o desempenho, pois o banco de dados não tenta repará-la - apenas trava a consulta atual.