Em alguns casos de migrações recentes de bases, uma das questões mais importantes levantadas foi como fazer para entender todos os dbs links que entram e saem, pois eles devem ser modificados depois de migrações massivas.
Db links de saída são simples: a DBA_DB_LINKS descreve todos os db links na base. E essa view vem sendo parte do banco (ao menos) desde o 7.3.4.
A parte complicada é como achar todos os db links de entrada. Depois do 12.2, a nova view chamada DBA_DB_LINK_SOURCES mostra as informações das bases fonte que abriram db links na base local.
Então, e a respeito das bases versão 12.1 e anteriores?
Uma comunidade de discussão do fórum MOS DBA dá diversas idéias:
Opção 1: Bruno sugere "começar do logfile do listener; usando algum 'awk/sed/vi' onde pode ser possível extrair a lista das conexões "originais"... -> Dessa lista, identificar os servidores -> Procurar os db links em bases relevantes nesses servidores"
Pode funcionar mas pode ser um pouco chato se tivermos cerca de 100 ou mais servidores diferentes.
Opção 2: Brian sugere "consultar a V$SESSION para ver as sessões ativas do outro servidor. Dica... confira a coluna MACHINE para ver se corresponde ao nome do outro servidor. Consultar a V$SESSION só irá funcionar se o link estiver aberto na hora da consulta. Sendo assim, você talvez queira adicionar uma trigger de AFTER LOGON que escreve uma entrada de auditoria numa tabela se a conexão for daquele servidor."
Se você criar a trigger para inserir todas as conexões recebidas via db link, note que no 11g, você pode fazer isso usando o valor sys_context('USERENV','DBLINK_INFO') que vai nos dar toda a informação. Mas confira primeiro o Doc ID 2593966.1 onde o Bug 18974508 sys_context('userenv', 'dblink_info') retorna informações incompletas.
Mas antes do 10g, não há DBLINK_INFO, precisamos usar x$k2gte:
select username, osuser, status, sid, serial#, machine,
process, terminal, program from v$session
where saddr in (select k2gtdses from sys.x$k2gte);
Isso está documentado no Doc ID 332326.1. Como identificar uma sessão iniciada por uma transação remota distribuída? A tabela refeita x$k2gte contém o 2PC Global Transaction Entry. A coluna k2gtdses no x$k2gte tem o estado do objeto de sessão e isso pode ser mapeado para a coluna saddr da v$session.
Mas como o Mark explicou, o problema é que até a trigger termine a sessão, a sessão do db link remoto não é considerada existente e somente após uma conexão de sessão com sucesso o Oracle vai e atualiza os fatos relacionados sobre a sessão. O Oracle não garante consistência de leitura nas views v$ e as views v$ são baseadas em tabelas x$ que são realmente programas da área de armazenamento. Essas áreas são atualizadas em vários pontos na área lógica. É possível que uma trigger de logon não funcione nesse caso específico. Uma alternativa seria rodar o processo depois de X tempo que capta o que está lá e grava novas consultas remotas. Dito isso você irá precisar somente de uma fonte de captura remota onde você se procure um db link ou cada servidor cliente.
Um dos top experts, Mariami Kupatadze, nos deu uma maneira bem elegante de como encontrar sessões remotas executando em um db link usando x$k2gte, x$ktcxb, x$ksuse e v$session_wait numa query de SQL.
Uma versão mais detalhada chamada Identificando o uso de db link foi escrito por John Hallas em 2015.
Resumindo: para bases de 7.3 até 12.1 crie um job que capture as transações distribídas baseado no script cedido no Doc ID 104420.1 "Script to show Active Distributed Transactions". E você pode modificar os scripts para captar além das transações remotas ativas. Para o 12.2 e adiante, é só usar a view DBA_DB_LINK_SOURCES.
Comments