Oracle Live

02/04/2016

Parsea 10046 para 10g

Filed under: Debugger,Scripts — mogukiller @ 1:29 am
Tags:

Todos nos hemos encontrado con el problema de saber que esta haciendo una sesion y donde esta invirtiendo el tiempo. Con las vistas de base de datos y la frecuencia de sampleo (1 seg para la v$action_session_history, 1 min para la dba_hist_activ_sess_hist y 1 hora para las vistas del repositorio de awr) seguramente estemos perdiendo información de lo que esta pasando. Una posible solución es habilitar las trazas 10046 y luego analizar con tkprof. El problema del tkprof es que te agrupa las queries perdiendo la vision de la secuencialidad de las queries. Para solucionar esto esta este script en perl.
Este script es valido para versiones 10g.


./parsea_10046_10g prueba_ora_14145.trc >salida.out

/*EJ. SALIDA
[09:05:42] Num query: 50    --> sqlid: 7f8f94e0   SELECT * FROM EMPLEADOS WHERE ROWNUM<10
[09:06:07] Num query: 51    --> sqlid: 7f8f0490   UPDATE EMPLEADOS SET ID_DEPARTAMENTO=4 WHERE ID_EMPLEADO=10
[09:06:10] Num query: 52    --> sqlid: 0          COMMIT
[09:06:29] Num query: 53    --> sqlid: 7f8ee5e8   SELECT NOMBRE FROM EMPLEADOS WHERE ID_EMPLEADO=10
[09:06:49] Num query: 71    --> sqlid: 7f8ee248   SELECT * FROM PRUEBA_RMAN WHERE ROWNUM<10
*/

#!/usr/bin/perl

use Data::Dumper;
use Time::Local;

my $InSQL = 0;
my $InBIND = 0;
my $BIND_num = 0;
my $SQL_TEXT="";
my $cursor_actual;
my %hash_cursor_ad =();
my %hash_sqlid_sqltext;
my @sql_parsed;
my @bin_variables;
my $InTime = 0;
my $date_inicio;
my $time_total_msec = 0;
my $initial_time = 0;
my $NumQuery =0;

#####################################################
###
###			INTERNAL FUNCTIONS
###
#####################################################
sub printv
{ 
	print "-> $_[0];\n"; 
}

sub printa
{   
	foreach (@_)
	{
		print "$_-->\n";
	}
}

#---------------------------------------------------
#
# INPUT PARAMETER TYPE: (HASH, VARIABLE, VARIABLE)
# INPUT PARAMETERS:
#	1) HASH -> este has contiene la relacion entre cursores y address
#	2) Esta variable contiene el cursos obtenido del PARSING CURSOR de la traza
#	3) Esta variable contiene el address actual del cursor obtenido del PARSING CURSOR de la traza
#
# OUTPUT PARAMETER TYPE: (HASH)
# OUTPUT PARAMETERS:
#	1) HASH -> este has contiene la relacion entre cursores y address, tras agregar el cursor y el address de entrada
#
#---------------------------------------------------

sub hash_add_cur_ad (\%$$)
{

	#print @_;
	my %_hash_cursor_ad;
	my ($_hash_cursor_ad, $_incursor, $_inad) = @_;
	#printv ($_incursor);
	#printv ($_inad);
    #if (exists($_hash_cursor_ad{$_incursor})) {
    #    #print "$_incursor already exists in the hash\n";
    #}
    #else {
        $_hash_cursor_ad{$_incursor} = $_inad;
	#	#print "$_incursor already added in hash\n";
    #}
	return (%_hash_cursor_ad);
	undef %_hash_cursor_ad;
	undef $_incursor;
	undef $_inad;
}


#---------------------------------------------------
#
# INPUT PARAMETER TYPE: (HASH, VARIABLE, VARIABLE)
# INPUT PARAMETERS:
#	1) HASH -> este has contiene la relacion entre address y sqltext
#	2) Esta variable contiene el address obtenido del PARSING CURSOR de la traza
#	3) Esta variable contiene el sqltext del address obtenido del PARSING CURSOR de la traza
#
# OUTPUT PARAMETER TYPE: (HASH)
# OUTPUT PARAMETERS:
#	1) HASH -> este has contiene la relacion entre address y sqltext, tras agregar el address y el sqltext de entrada
#
#---------------------------------------------------

sub hash_add_ad_sqltext (\%$$)
{	
	my %_hash_ad_sqltext; 
	$_hash_ad_sqltext = $_[0];
	my $_inad = $_[1];	
	my @_insqltext = @{$_[2]};
	foreach my $elemento (@_insqltext)
	{
		push(@{$_hash_ad_sqltext{$_inad}}, $elemento); 
	}
	return (%_hash_ad_sqltext);
	undef %_hash_ad_sqltext;		
}

#---------------------------------------------------
#
# INPUT PARAMETER TYPE: (string)
# INPUT PARAMETERS:
#	1) HASH -> sqltext sin parsear
#
# OUTPUT PARAMETER TYPE: (Array)
# OUTPUT PARAMETERS:
#	1) Array -> SQL en el primer elemento y nombre de las bind varialbes en el resto.
#
#---------------------------------------------------
sub parsea_sqltext
{
	my @_sql_parsed;
	my $_sqltext = $_[0];
	# print "DEBUG parsea_sqltext $_sqltext \n";
	$_sql_parsed[0] = $_sqltext;
	#print "$_sqltext \n";
	while ( $_sqltext =~ /(:\"?\w+"?)/g ) 
	{
		push @_sql_parsed, $1;
		#print "$1 \n";
	}
	return (@_sql_parsed);
	undef @_sql_parsed;
	undef $_sqltext;
}

#---------------------------------------------------
#
# INPUT PARAMETER TYPE: (Array, String )
# INPUT PARAMETERS:
#	1) Array -> Valores Bind Variables
#	2) String	-> Cursor asociado al sqlid
#
# OUTPUT PARAMETER TYPE: (String)
# OUTPUT PARAMETERS:
#	1) String -> SQL Parseada con sus bind varialbes
#
#---------------------------------------------------
sub replace_bin_variable
{
	
	# my @_bin_variables = @{$_[0]};
	# my $_cursor_actual = $_[1];
	# print "Cursor actual $_cursor_actual \n"; 
	
	# print "Valor sql_id: $_sqlid \n";
	
	#my $_sqltext =  $hash_sqlid_sqltext{$_sqlid};
	
	#undef @_bin_variables;
	
}

# -------------------------------
#   MAIN   
# -------------------------------

system("clear");
print "\n\n\n";

while (<>) {
$MyLine = $_;
$LineNum = $LineNum + 1;

if (($InTime == 0) && ($MyLine =~ /^\*\*\*/))
{
	$InTime=1;
	$MyLine =~ s/^\*\*\*//;
	$year = (split(/-/, $MyLine))[0];
	$month = (split(/-/, $MyLine))[1];
	$resto = (split(/-/, $MyLine))[2];
	$day   = (split(/ /, $resto))[0];
	$resto = (split(/ /, $resto))[1];
	$hour  = (split(/:/, $resto))[0];
	$min   = (split(/:/, $resto))[1];
	$resto = (split(/:/, $resto))[2];
	$sec    = (split(/\./, $resto))[0];
	$date_inicio = timelocal($sec,$min,$hour,$day,$month,$year);	
}
 
if ($MyLine =~ /====/) {
	$InBIND = 0;
	$InSQL = 0;
	$BIND_num = 0;
	$cursor=0;
	$SQL_TEXT="";
	#print "$MyLine\n";
}

# If END OF STMT found, stop printing
if (($InSQL==1) && ($MyLine =~ /END OF STMT/ )) {
	@sql_parsed =();
	@sql_parsed = parsea_sqltext($sqltext);
	$sqltext ="";
	# print "Print SQL_PARSED";
	# print Dumper @sql_parsed;
	%hash_ad_sqltext=hash_add_ad_sqltext(%hash_ad_sqltext,$ad,\@sql_parsed);
	# print "Despues de la llamada \n";
	# print "DEBUG Guardamos query\n";
	# print Dumper(\%hash_ad_sqltext);	
	$InSQL = 0;
	
}

# In matching pattern, continue printing
if ($InSQL == 1) {
	$sqltext = $sqltext . $MyLine; 
	#print "----->>>" . $sqltext;
	#print $MyLine;
}

# If PARSING IN CURSOR found, start printing
if ($MyLine =~ /PARSING IN CURSOR/) 
{
	#print "-- " . $MyLine;
	$MyLine =~ s/^.*PARSING IN CURSOR #//;
	$cursor = (split(/\s+/, $MyLine))[0];
	@cursor_info = split (/ +/,$MyLine);
	foreach $item (@cursor_info)
	{
		if ($item =~ /tim=/) {
			$time=(split(/=/, $item))[1];
			chomp($time);
			if ( $InTime == 1 ) { 
				$initial_time = $time;
				$InTime = 2;
			}
		}
		elsif ($item =~ /hv=/) {
			$hv=(split(/=/, $item))[1];
			chomp($hv);
		}
		elsif ($item =~ /sqlid=/) {
			$sqlid=(split(/=/, $item))[1];
			$sqlid =~ s/\'//g;
			chomp($sqlid);
		}
		elsif ($item =~ /ad=/) {
			$ad=(split(/=/, $item))[1];
			$ad =~ s/\'//g;
			chomp($ad);
		}
	}

	%hash_cursor_ad=hash_add_cur_ad(%hash_cursor_ad,$cursor,$ad);
	#print Dumper(\%hash_cursor_ad);
	$InSQL = 1;
}
 
if ($MyLine =~ /BINDS #/) {
	$InBIND = 1;
	$MyLine =~ s/^.*BINDS #//;
	$MyLine =~ s/://;
	$cursor_actual = (split(/\s+/, $MyLine))[0];
	#print "DEBUG: BINDS# Cusor actula $cursor_actual \n";
	# Limpiamos el array anterior
	@bin_variables = ();
	
}
if (($InBIND==1) && ($MyLine =~ /value=/ )) {
	if ( $MyLine =~ /(value=\"?\w+"?)/g )
	{
		$valor_bind = (split(/=/, $1))[1];
		#print "DEBUG: Bind Value: $valor_bind \n";
		push(@bin_variables, $valor_bind);
	}
	else
	{
		#print "DEBUG: Bind Value: ######## \n";
		push(@bin_variables, "######");
	}			
}

# Imprimimos las queries sin bind varialbes

if ( $MyLine =~ /EXEC/ )
{
	$MyLine =~ s/^.*EXEC #//;
	$cursor_actual = (split(/:/, $MyLine))[0];
	$sqlid = $hash_cursor_ad{$cursor_actual};
	
	if ($InBIND==0) {
		$sql_text = $hash_ad_sqltext{$sqlid}[0];		
	}

	if ($InBIND==1) {
		$InBIND = 0;			
		@sql_array = @{$hash_ad_sqltext{$sqlid}};	
		$sql_text = $sql_array[0];	
		
		for ( my $contador=1; $contador<@sql_array; $contador++ )
		{
			$bind_name = $sql_array[$contador];
			$bind_value = $bin_variables [ $contador -1 ];
			$sql_text =~ s/$bind_name/$bind_value/;		
		}
		
	}
	#Extraemos hora ejecucion
	
	@cursor_info = split (/,/,$MyLine);
	foreach $item (@cursor_info)
	{
		if ($item =~ /tim=/) {
			$time_end=(split(/=/, $item))[1];
			chomp($time_end);
		} 
				
	}
	$NumQuery ++;
	($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($date_inicio + int(($time_end - $initial_time)/1000000));		
	printf ("\n[%02d:%02d:%02d] Num query: %-5d --> sqlid: %-10s \n",$hour,$min,$sec,$NumQuery, $sqlid);
	printf ("%s",$sql_text);
}	
}

Dejar un comentario »

Aún no hay comentarios.

RSS feed for comments on this post. TrackBack URI

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

Blog de WordPress.com.

A %d blogueros les gusta esto: