Ao administrar bancos Oracle em arquitetura Multitenant, um desafio comum é entender como o consumo de CPU está distribuído entre o
CDB$ROOT e os PDBs (Pluggable Databases). Pensando nisso, desenvolvi um script simples em Bash que coleta esses dados diretamente da v$sys_time_model e exibe a porcentagem de uso para cada PDB.Este script é bastante útil para consolidar as informações de CPU de ambientes Standard Edition com mais de um PDB, uma vez que nesta versão não existe uma visão consolidada, sendo necessário consultar manualmente em cada um dos PDBs (não que isso seja um problema). Porém com o script nos da mais possibilidades, como por exemplo agendar e armazenar dados das coleta em uma tabela, por exemplo.
Objetivo
Coletar o tempo total de CPU utilizado no
CDB$ROOT(base de referência);-
Coletar o tempo de CPU utilizado por cada PDB aberto em modo
READ WRITE; -
Calcular e exibir o percentual de uso de cada PDB em relação ao total da instância.
Utiliza-se a métrica DB CPU da visão v$sys_time_model, convertida de microssegundos para segundos, para avaliar o uso de CPU. A métrica é coletada para o CDB$ROOT e para cada PDB individualmente, com o cálculo percentual feito via awk.
O Script
Gere um script .sh com os comandos abaixo e posteriormente execute-o.
#!/bin/bash export PATH=$ORACLE_HOME/bin:$PATH PDB_LIST=$(mktemp) declare -A CPU_VALUES # Coleta CPU do CDB$ROOT ROOT_CPU=$(sqlplus -s "/ as sysdba" <<EOF ALTER SESSION SET CONTAINER = CDB\$ROOT; SELECT ROUND(value / 1000000, 2) FROM v\$sys_time_model WHERE stat_name = 'DB CPU'; EXIT; EOF ) ROOT_CPU=$(echo "$ROOT_CPU" | tr -d '\n\r[:space:]') [ -z "$ROOT_CPU" ] && ROOT_CPU=0 # Cabeçalho echo "PDB_NAME | CPU_SECONDS | % USO" echo "-------------------|-------------|--------" printf "%-19s| %-12s| %6s%%\n" "CDB\$ROOT" "$ROOT_CPU" "100.00" # Lista de PDBs abertos sqlplus -s "/ as sysdba" <<EOF > /dev/null SPOOL $PDB_LIST SELECT TRIM(name) FROM v\$containers WHERE con_id > 2 AND open_mode = 'READ WRITE'; SPOOL OFF EXIT; EOF # Coleta CPU por PDB while IFS= read -r PDB; do PDB=$(echo "$PDB" | xargs) [ -z "$PDB" ] && continue CPU=$(sqlplus -s "/ as sysdba" <<EOF ALTER SESSION SET CONTAINER = "$PDB"; SELECT ROUND(value / 1000000, 2) FROM v\$sys_time_model WHERE stat_name = 'DB CPU'; EXIT; EOF ) CPU=$(echo "$CPU" | tr -d '\n\r[:space:]') [[ -z "$CPU" || "$CPU" == *ORA-* ]] && CPU=0 CPU_VALUES["$PDB"]="$CPU" done < "$PDB_LIST" # Apresentação final for PDB in "${!CPU_VALUES[@]}"; do CPU_VAL=${CPU_VALUES[$PDB]} PCT=$(awk -v used="$CPU_VAL" -v total="$ROOT_CPU" 'BEGIN { if (total > 0) printf "%.2f", (used/total)*100; else print "0.00" }') printf "%-19s| %-12s| %6s%%\n" "$PDB" "$CPU_VAL" "$PCT" done rm -f "$PDB_LIST"
Execução:
[oracle@dbsystem23ai tmp]$ [oracle@dbsystem23ai tmp]$ sh coletar_cpu_pdbs.sh PDB_NAME | CPU_SECONDS | % USO -------------------|-------------|-------- CDB$ROOT | 36383.27 | 100.00% LAMIMDB_PDB2 | 4.38 | 0.01% LAMIMDB_PDB1 | 11785.75 | 32.39% [oracle@dbsystem23ai tmp]$
Observações:
- A métrica utilizada (DB CPU) pode não refletir 100% do consumo real da máquina (existem outras como background cpu time).
- O script ignora PDBs em MOUNTED ou READ ONLY.
- É necessário executar como SYSDBA.
- Pode ser agendado via cron para coleta periódica.
Comentários
Postar um comentário