#!/opt/local/bin/perl # Script to dump the ddl_log.log file created in mysql during ddl operations. # Mainly used by the partitioning function introduced in 5.1 # # Structure of the file # Offsets in each entry # DDL_LOG_ENTRY_TYPE_POS 0 # DDL_LOG_ACTION_TYPE_POS 1 # DDL_LOG_PHASE_POS 2 # DDL_LOG_NEXT_ENTRY_POS 4 # DDL_LOG_NAME_POS 8 # Offsets in first entry (the header) # DDL_LOG_NUM_ENTRY_POS 0 # DDL_LOG_NAME_LEN_POS 4 # DDL_LOG_IO_SIZE_POS 8 # Header # offset size Description # 0 4 Number of entries in the ddl log # 4 4 FN_LEN - Maximum length of name strings in the log # (fixed/null padded) # 8 4 IO_SIZE - Fixed size of each entry # First byte in each entry # 'e' - DDL_LOG_EXECUTE_CODE: # This is a code that indicates that this is a log entry to # be executed, from this entry a linked list of log entries # can be found and executed. # 'l' - DDL_LOG_ENTRY_CODE: # An entry to be executed in a linked list from an execute log # entry. # 'i' - DDL_IGNORE_LOG_ENTRY_CODE: # An entry that is to be ignored # Second byte in each entry # The type of action that a DDL_LOG_ENTRY_CODE entry is to # perform. # 'd' - DDL_LOG_DELETE_ACTION: # Delete an entity # 'r' - DDL_LOG_RENAME_ACTION: # Rename an entity # 's' - DDL_LOG_REPLACE_ACTION: # Rename an entity after removing the previous entry with the # new name, that is replace this entry. # First real entry # offset size Description # 4096 1 DDL_LOG_ENTRY_TYPE - 'e'/'l'/'i' # 4097 1 DDL_LOG_ACTION_TYPE - 'd'/'r'/'s' # 4098 1 PHASE (REPLACE have two phases, remove the target then rename) # 4099 1 UNUSED - only for alignment # 5000 4 Next entry pos - entry number of next linked entry # 5004 4 Internal table/partition name # my $ddl_log_filename = $ARGV[0]; my $num_of_entries; my $name_length; my $block_length; my $raw_data; open FH, $ddl_log_filename or die "Could not open $ddl_log_filename"; # read header to get sizes of names and blocks read FH, $raw_data, 12 or die "Failed to read header"; ($num_of_entries, $name_length, $block_length) = unpack("VVV", $raw_data) or die "Failed to unpack header"; print "Header: Num entries: $num_of_entries Name length: $name_length Block length $block_length\n"; my $curr_pos = $block_length; my $curr_entry = 1; my $entry_type; my $entry_action; my $entry_phase; my $entry_next; my $entry_name; my $entry_from_name; my $entry_handler_name; for (my $i= 1; $i < $num_of_entries ; $i++) { seek (FH, $block_length * $i, 0) or die "Failed to seek to entry $i"; read FH, $raw_data, $block_length or die "Failed to read entry $i"; ($entry_type, $entry_action, $entry_phase, undef, $entry_next, $entry_name, $entry_from_name, $entry_handler_name) = unpack("aaaaVZ$name_lengthZ$name_lengthZ$name_length", $raw_data); print "Entry $i type $entry_type action $entry_action next $entry_next\n name $entry_name\n"; if ($entry_from_name ne "") { print " from name $entry_from_name\n"; } if ($entry_handler_name ne "") { print " handler name $entry_handler_name\n"; } if ($entry_type eq "e") { print_execute($i); } else { print "not 'e' entry ($entry_type)\n"; } } sub print_execute() { my ($entry_nr) = @_; seek (FH, $block_length * $entry_nr, 0) or die "Failed to seek to entry $entry_nr"; read FH, $raw_data, $block_length or die "Failed to read entry $entry_nr"; ($entry_type, $entry_action, $entry_phase, undef, $entry_next, $entry_name, $entry_from_name, $entry_handler_name) = unpack("aaaaVZ$name_lengthZ$name_lengthZ$name_length", $raw_data); if ($entry_type eq "i") { print "IGNORE Entry $entry_nr type $entry_type action $entry_action next $entry_next\n name $entry_name\n"; if ($entry_from_name ne "") { print " from name $entry_from_name\n"; } if ($entry_handler_name ne "") { print " handler name $entry_handler_name\n"; } } elsif ($entry_type eq "e") { print "LOG Entry $entry_nr type $entry_type action $entry_action next $entry_next\n name $entry_name\n"; if ($entry_from_name ne "") { print " from name $entry_from_name\n"; } if ($entry_handler_name ne "") { print " handler name $entry_handler_name\n"; } } else { print "UNKNOWN Entry $entry_nr type $entry_type action $entry_action next $entry_next\n name $entry_name\n"; } print_execute($entry_next); } #while (($curr_pos / $block_length) <= $num_of_entries) #{ #seek (FH, $curr_pos, 0) or die "Failed to seek to $curr_pos (entry $curr_entry)"; #read FH, $raw_data, $block_length or die "Failed to read entry $curr_entry"; #($entry_type, $entry_action, $entry_phase, undef, $entry_next, $entry_name, $entry_from_name, $entry_handler_name) = unpack("aaaaVZ$name_lengthZ$name_lengthZ$name_length", $raw_data); #print "Entry $curr_entry type $entry_type action $entry_action next $entry_next\n name $entry_name\n"; #if ($entry_from_name ne "") ##{ ##print " from name $entry_from_name\n"; #} #if ($entry_handler_name ne "") #{ #print " handler name $entry_handler_name\n"; #} #$curr_entry = $entry_next; #$curr_pos = $entry_entry * $block_length; #}