Conteúdo voltado para banco de dados Oracle e SQL Server

Administração Archive

O erro ORA-22297: warning: Open LOBs exist at transaction commit time ocorre quando o usuário faz alguma manipulações colunas do tipo CLOB ou BLOB e por algum motivo não fechou o LOB conforme deveria antes de fazer o commit.

Abaixo segue um exemplo simples que poderia ter evitado o problema:

DBMS_LOB.CLOSE(myFile);
DBMS_LOB.CLOSE(myBlob);
COMMIT;

Para solucionar o problema precisei fazer um rebuild no CLOB e na PK da tabela em questão. O primeiro passo foi listar os índices da tabela:

desct DBUSER.TB_CLOB
select * from dba_indexes where table_name = 'TB_CLOB' and owner='DBCLOB';

Após verificar os índices, fiz o move no CLOB e o rebuild na PK:

ALTER TABLE DBUSER.TB_CLOB MOVE LOB (CLOB_ARQUIVO) STORE AS (TABLESPACE TD_USER);
alter index DBUSER.PK_CLOB rebuild;

Após realizar esse procedimento conseguimos executar o processo sem retornar o erro:

ORA-22297: warning: Open LOBs exist at transaction commit time

Em alguns blogs e sites de referência, a maioria das pessoas disseram que essa mensagem é apenas informativa, porém só consegui rodar o processo após o reubild no CLOB e na PK da tabela.

Fica a dica.

Algumas operações de tecnologias podem ser paralelizadas utilizando mais CPUs para processar determinadas tarefas, e no banco de dados não é diferente. A opção PARALLEL X, onde X é a quantidade de cores a ser utilizada permite dividir a consulta em pequenos pedaços fazendo com que cada processador execute parte da query.

No exemplo abaixo estou paralelizando a consulta entre 20 cpus com o comando PARALLEL 20 e suspendi a geração de REDO LOG com o NOLLOGGING. Essa operação é lenta, pois está comprimindo uma tabela de 500GB e movendo para outra tablespace, a TD_MOVELOB:

ALTER TABLE GALOMG.TB_LOG COMPRESS FOR OLTP;
ALTER TABLE GALOMG.TB_LOG MOVE TABLESPACE TD_MOVELOB NOLOGGING PARALLEL 20;

Para checar se a consulta está paralelizada, basta executar o select abaixo na LONGOPS que trará uma linha para cada processo dividido:

SELECT inst_id,sid, serial#, opname, username,start_time,last_update_time,
round(time_remaining/60,2) "REMAIN MINS", round(elapsed_seconds/60,2) "ELAPSED MINS", round((time_remaining+elapsed_seconds)/60,2) "TOTAL MINS", 
ROUND(SOFAR/TOTALWORK*100,2) "%_COMPLETE", message
FROM gv$session_longops 
WHERE TOTALWORK != 0 AND sofar<>totalwork AND time_remaining > 0;

Abaixo o resultado da query, onde msotra que cada pedaço da query possui um SID diferente, mesmo que a tabela seja a mesma: GALOMG.TB_LOG !

Basta executar a query várias vezes para consultar o tempo que cada pedaço da query está sendo executado.

Olá pessoal,
hoje vou passar algumas dicas para desligar corretamente seu ambiente do Oracle RAC. Precisei fazer uma manutenção em apenas 1 dos nós e as vezes temos dúvidas de qual procedimento usar, qual é melhor, mais rápido, etc.

Há duas maneiras legais de para uma instância que são utilizando os comando SRVCTL (servercontrol) ou o CRSCTL (clustercontrol). A diferença básica de um para o outro é que o ClusterControl vai parar a instância do ASM automaticamente e deve ser executado como ROOT.

Maos á obra !

Utilizando o SRVCTL teremos as seguintes opções:

srvctl stop instance -d database -i instancia -o abort
srvctl start instance -d database -i instance
srvctl status database -d database

srvctl stop asm -node hostname -stopoption IMMEDIATE
srvctl start asm -node hostname
srvctl status asm

Utilizando o CRSCTL teremos as seguintes opções:

crsctl stop crs
crsctl start crs
crsctl stat res -t init
crsstat

Com esses comandos acima você consegue facilmente parar e subir os serviços do Oracle

Um recurso pouco utilizado, porém muito útil no Oracle Database é setar informações da aplicação nas views de sistema V$SESSION / GV$SESSION. É comum alguma consulta estar impactando o ambiente e as informações contidas nas views de sistema e as informações não serem tão precisas a ponto de ir direto no problema. É possível, por exemplo, colocar o nome da aplicação ou da etapa do processo em que está sendo executado, e com isso você saberia se o processo que está impactando é o início ou o fim do processo.

Mãos á obra ..

Abra uma query no Oracle e execute a query abaixo. Nesse caso, eu estou informando que minha aplicação é o controle de estoque e que o procedimento que está sendo executado é a baixa de produtos devolvidos:


exec dbms_application_info.set_module(module_name => 'Controle de Estoque',action_name => 'Baixa dos produtos devolvidos');

PL/SQL procedure successfully completed.

Após execução do pacote acima, a query na v$session será populada com os dados:


select osuser, module, action from v$session where action is not null

noraldino <strong>Controle de Estoque Baixa dos produtos devolvidos</strong>


As informações contidas no pacote podem ser customizadas de acordo com sua necessidade. É recomendado que esse procedimento seja repassado ao time de desenvolvimento para que seja incluído esse pacote antes das execuções de procedimentos, pois na hora do troubleshooting essas informações podem ser muito úteis e poupar muito tempo dos envolvidos.

Enjoy !

Esse erro comum ocorre quando você tenta executar uma operação em uma tabela que foi alterada e a transação ainda está pendente. No nosso caso, estávamos tentando truncar uma tabela de B.I. e o erro era retornado instantaneamente: ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired !

O select abaixo ajudou a identificar a causa raiz, ele lista quais sessões estão aguardando commit ou roolback. No meu caso foi uma transação aberta há mais de 30 dias e, alinhando com a área, matamos a sessão:

SELECT O.OBJECT_NAME, S.SID, S.SERIAL#, P.SPID, S.PROGRAM,S.USERNAME,
S.MACHINE,S.PORT , S.LOGON_TIME,SQ.SQL_FULLTEXT 
FROM V$LOCKED_OBJECT L, DBA_OBJECTS O, V$SESSION S, 
V$PROCESS P, V$SQL SQ 
WHERE L.OBJECT_ID = O.OBJECT_ID 
AND L.SESSION_ID = S.SID AND S.PADDR = P.ADDR 
AND S.SQL_ADDRESS = SQ.ADDRESS;

Dica: Em ambiente Oracle RAC troque o V$ por GV$ !

Faça bom uso do script.

Criei um banco do zero, movi os dados da instância anterior para o mesmo e fui conectar no RMAN/CATALOGO para ver se estava tudo ok. No exato momento recebi o segunte erro:

RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of crosscheck command at 07/18/2018 15:15:45
RMAN-12010: automatic channel allocation initialization failed
RMAN-06004: ORACLE error from recovery catalog database: RMAN-20001: target database not found in recovery catalog

Esse erro acontece porque o banco de dados criado não foi registrado no catálogo. Um comando extremamente simples resolve o problema, basta registrar o database no catálogo : )

Com o usuário Oracle e as variáveis do banco setadas, execute o seguinte comando para conectar no banco de dados:

rman target / catalog rman/mypassword@repositorio;

A seguinte mensagem de sucesso será apresentada na tela:

Recovery Manager: Release 12.1.0.1.0 - Production on Wed Jul 18 15:15:39 2018

Copyright (c) 1982, 2013, Oracle and/or its affiliates.  All rights reserved.

connected to target database: GALOMINEIRO (DBID=131313131313)
connected to recovery catalog database

Após conectar, basta digitar o comando register database para que o banco de dados seja registrado no catálogo:

RMAN> register database;

E acompanhe a execução do procedimento:

database registered in recovery catalog
starting full resync of recovery catalog
full resync complete

Pronto! A partir desse momento o banco de dados estará devidamente registrado no catálogo. Basta conectar no catálogo e rodar o select abaixo para garantir que o banco está de fato no catalogo:

select * from rc_database where name = 'VS24'
65432165	50023546	131313131313	GALOMINEIRO	654984613565	18/07/18

Há poucos dias atrás precisei instalar os agentes do Oracle Cloud Control 13c em 3 servidores de produção, porém ele dava o erro em que a porta xxx estava sendo usada. Verifiquei que já haviam outros agentes rodando nas máquinas e eram referentes á versões anteriores, para que os novos agentes fossem instalados, esse antigos deveriam ser removidos.

Mãos á obra:

Localize o agent_home da instalação anterior e exporta a variável AGENT_HOME. No meu caso ela estava em /u01/app/oracle/agent12c/core/12.1.0.4.0:


export AGENT_HOME=/u01/app/oracle/agent12c/core/12.1.0.4.0

Em seguida execute o comando abaixo para remoção do agente:


$perl $AGENT_HOME/sysman/install/AgentDeinstall.pl -agentHome $AGENT_HOME

Após executar o código acima, a mensagem abaixo informará na tela o progresso da desinstalação:

** Esse processo só retira o agente do servidor, para retirar do Oracle Cloud Control deverá ser feita uma operação á parte.
Agent Oracle Home: /u01/app/oracle/agent12c/core/12.1.0.4.0

agentHome = /u01/app/oracle/agent12c/core/12.1.0.4.0

NOTE: The agent base directory: /u01/app/oracle/agent12c will be removed after successful deinstallation of agent home.

DetachHome Command executed:/u01/app/oracle/agent12c/core/12.1.0.4.0/oui/bin/runInstaller -detachHome -force -depHomesOnly -silent ORACLE_HOME=/u01/app/oracle/agent12c/core/12.1.0.4.0 -waitForCompletion -invPtrLoc /u01/app/oracle/agent12c/core/12.1.0.4.0/oraInst.loc
Iniciando Oracle Universal Installer…

Verificando espaço de swap: deve ser superior a 500 MB. 99999 MB Reais Passado
The inventory pointer is located at /u01/app/oracle/agent12c/core/12.1.0.4.0/oraInst.loc
‘DetachHome’ bem-sucedido.
Iniciando Oracle Universal Installer…

Verificando espaço de swap: deve ser superior a 500 MB. 99999 MB Reais Passado
The inventory pointer is located at /u01/app/oracle/agent12c/core/12.1.0.4.0/oraInst.loc
Não foi possível atualizar o Oracle home ‘/u01/app/oracle/agent12c/sbin’ pois ele não existe.

Deinstall Command executed:/u01/app/oracle/agent12c/core/12.1.0.4.0/oui/bin/runInstaller -deinstall -silent “REMOVE_HOMES={/u01/app/oracle/agent12c/core/12.1.0.4.0}” -waitForCompletion -removeAllFiles -invPtrLoc /u01/app/oracle/agent12c/core/12.1.0.4.0/oraInst.loc
Iniciando Oracle Universal Installer…

Verificando espaço de swap: deve ser superior a 500 MB. 99999 MB Reais Passado
Preparando para iniciar o Oracle Universal Installer de /tmp/OraInstall2018-06-28_10-38-07AM. Aguarde …Oracle Universal Installer, Versão 11.1.0.12.0 Produção
Copyright (C) 1999, 2014, Oracle. Todos os direitos reservados.

Iniciando desinstalação

Desinstalação em andamento (Quinta-feira, 28 de Junho de 2018 10h38min12s BRT)
O assistente de configuração “Agent Deinstall Assistant” foi bem-sucedido
……………………………………………………… 100% Concluído.

Desinstalação bem-sucedida

Fim das fases de instalação.(Quinta-feira, 28 de Junho de 2018 10h38min20s BRT)
Fim das desinstalações
Verifique “/u01/app/oraInventory/logs/silentInstall2018-06-28_10-38-07AM.log” para obter mais detalhes.
cannot fetch initial working directory: Arquivo ou diretório não encontrado at /u01/app/oracle/agent12c/core/12.1.0.4.0/sysman/install/AgentDeinstall.pl line 303
cannot fetch initial working directory: Arquivo ou diretório não encontrado at /u01/app/oracle/agent12c/core/12.1.0.4.0/sysman/install/AgentDeinstall.pl line 303
cannot fetch initial working directory: Arquivo ou diretório não encontrado at /u01/app/oracle/agent12c/core/12.1.0.4.0/sysman/install/AgentDeinstall.pl line 303

NOTE: The targets monitored by this Management Agent will not be deleted in the Enterprise Manager Repository by this deinstall script. Make sure to delete the targets manually from the Cloud Control Console for a successful deinstallation.

Numa bela tarde de terça-feira (12/06/2018) me deparo com esse erro bacana ao tentar colocar uma PK de uma tabela online .. Os scripts que eu tentei executar sempre tomavam esse erro. A causa desse problema foi um rebuild de índice PK que parei no meio do processo com um alter system kill session e o mesmo ficou incompleto.

A solução estava num doc id do MOS 375856.1 nomeado de: Session Was Killed During The Rebuild Of Index ORA-08104 : )

Basicamente é rodar esse script na instância que está ocorrendo o erro e em seguida rodar o rebuild dos índices:

DECLARE
isClean BOOLEAN;
BEGIN
isClean := FALSE;
WHILE isClean=FALSE
LOOP
isClean := dbms_repair.online_index_clean(
dbms_repair.all_index_id, dbms_repair.lock_wait);
dbms_lock.sleep(10);
END LOOP;
END;


Até a próxima.

 

 

Tarefa comum e corriqueira de um DBA é criar novos hosts para testes, ambientes de produção, desenvolvimento e homologação. Há poucos dias atrás precisei criar um servidor para instalação do Oracle Cloud Control 13c e fui surpreendido com a facilidade em alterar o nome de um servidor.

Nas versões anteriores era preciso alterar o arquivo /etc/hosts e reiniciar o S.O., porém na versão 7 basta digitar os comandos abaixo:

1 º – Checar o nome do servidor:

[root@localhost ~]# hostnamectl status
Static hostname: localhost.localdomain
Icon name: computer-vm
Chassis: vm
Machine ID: 5e2ea38c44ec49a497be3d6919cd9e96
Boot ID: 1996d9bfa13b48978e6cf411711a5e21
Virtualization: xen
Operating System: Oracle Linux Server 7.4
CPE OS Name: cpe:/o:oracle:linux:7:4:server
Kernel: Linux 4.1.12-94.3.9.el7uek.x86_64
Architecture: x86-64

2 º – Alterar o nome do servidor:

[root@localhost ~]# hostnamectl set-hostname SERVER002

3º – Checar o nome do servidor

[root@localhost ~]# hostnamectl status
Static hostname: SERVER002.localdomain
Icon name: computer-vm
Chassis: vm
Virtualization: xen
Operating System: Oracle Linux Server 7.4
CPE OS Name: cpe:/o:oracle:linux:7:4:server
Kernel: Linux 4.1.12-94.3.9.el7uek.x86_64
Architecture: x86-64

Foi só executar o passo 2 que o servidor já teve seu nome alterado, nem foi preciso reiniciar o S.O. para atingir tal objetivo.

Tenho um servidor de banco de dados que possui diversas instâncias do Oracle rodando sob um único ASM e recentemente precisei fazer um levantamento de quais eram os maiores bancos dentro dos DISKGROUPs de FRA e DATA. Inicialmente fiz um select em cada instância e joguei para uma planilha, mas .. são 23 instâncias, então certamente esse não era o melhor caminho : )

O script abaixo deve ser rodado na instância do ASM, basta trocar o que está na linha: WHERE gname=’FRA_ASM_DG’ pelo nome do seu diskgroup.

col gname form a10
col dbname form a10
col file_type form a14

SELECT
    gname,
    dbname,
    file_type,
    round(SUM(space)/1024/1024) mb,
    round(SUM(space)/1024/1024/1024) gb,
    COUNT(*) "#FILES"
FROM
    (
        SELECT
            gname,
            regexp_substr(full_alias_path, '[[:alnum:]_]*',1,4) dbname,
            file_type,
            space,
            aname,
            system_created,
            alias_directory
        FROM
            (
                SELECT
                    concat('+'||gname, sys_connect_by_path(aname, '/')) full_alias_path,
                    system_created,
                    alias_directory,
                    file_type,
                    space,
                    level,
                    gname,
                    aname
                FROM
                    (
                        SELECT
                            b.name            gname,
                            a.parent_index    pindex,
                            a.name            aname,
                            a.reference_index rindex ,
                            a.system_created,
                            a.alias_directory,
                            c.type file_type,
                            c.space
                        FROM
                            v$asm_alias a,
                            v$asm_diskgroup b,
                            v$asm_file c
                        WHERE
                            a.group_number = b.group_number
                        AND a.group_number = c.group_number(+)
                        AND a.file_number = c.file_number(+)
                        AND a.file_incarnation = c.incarnation(+) ) START WITH (mod(pindex, power(2, 24))) = 0
                AND rindex IN
                    (
                        SELECT
                            a.reference_index
                        FROM
                            v$asm_alias a,
                            v$asm_diskgroup b
                        WHERE
                            a.group_number = b.group_number
                        AND (
                                mod(a.parent_index, power(2, 24))) = 0
                    ) CONNECT BY prior rindex = pindex )
        WHERE
            NOT file_type IS NULL
            and system_created = 'Y' )
WHERE gname='FRA_ASM_DG'
GROUP BY
    gname,
    dbname,
    file_type
ORDER BY
4 desc;

O resultado deve ser algo parecido com o output abaixo:


GNAME      DBNAME     FILE_TYPE              MB         GB     #FILES
---------- ---------- -------------- ---------- ---------- ----------
FRA_ASM_DG LP142      ARCHIVELOG         241766        236         22
FRA_ASM_DG LP852      ARCHIVELOG         162494        159         66
FRA_ASM_DG LP90       ARCHIVELOG         147272        144          8
FRA_ASM_DG LP74       ONLINELOG           92376         90          8
FRA_ASM_DG LP65       ONLINELOG           81928         80          4
FRA_ASM_DG LP66       ONLINELOG           61448         60          4
FRA_ASM_DG LP98       ARCHIVELOG          58618         57        163
FRA_ASM_DG LP41       ARCHIVELOG          56984         56          8
FRA_ASM_DG LP42       ARCHIVELOG          33384         33         20
FRA_ASM_DG LP44       ONLINELOG           32776         32          4
FRA_ASM_DG LP22       ARCHIVELOG          31224         30       2807


Feito isso você terá noção de quais são os maiores bancos dentro do seu ASM, nesse caso, o LP142 está utilizando 236GB dentro do diskgroup de FRA e o LP22 está usando apenas 30GB.

Até a próxima.