Below is the list of changes that have just been committed into a local
5.1 repository of istruewing. When istruewing does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2008-06-04 15:57:58+02:00, istruewing@stripped +1 -0
Bug#36708 - extreme fragmentation of a table with blob records
Not to be pushed.
Temporarily added DBUG statements to show how record parts are
treated by each SQL statement.
storage/myisam/mi_dynrec.c@stripped, 2008-06-04 15:57:56+02:00, istruewing@stripped +292
-2
Bug#36708 - extreme fragmentation of a table with blob records
Added DBUG statements.
diff -Nrup a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c
--- a/storage/myisam/mi_dynrec.c 2008-03-31 09:40:37 +02:00
+++ b/storage/myisam/mi_dynrec.c 2008-06-04 15:57:56 +02:00
@@ -38,6 +38,7 @@ static int delete_dynamic_record(MI_INFO
uint second_read);
static int _mi_cmp_buffer(File file, const uchar *buff, my_off_t filepos,
uint length);
+static void debug_print_frames(MI_INFO *info);
#ifdef THREAD
/* Play it safe; We have a small stack when using threads */
@@ -324,6 +325,7 @@ static int write_dynamic_record(MI_INFO
ulong length;
my_off_t filepos;
DBUG_ENTER("write_dynamic_record");
+ DBUG_PRINT("ingo", ("INSERT record length: %lu", reclength));
flag=0;
@@ -360,6 +362,7 @@ static int write_dynamic_record(MI_INFO
goto err;
} while (reclength);
+ DBUG_EXECUTE_IF("ingo", debug_print_frames(info););
DBUG_RETURN(0);
err:
DBUG_RETURN(1);
@@ -395,6 +398,8 @@ static int _mi_find_writepos(MI_INFO *in
info->state->del--;
info->state->empty-= block_info.block_len;
*length= block_info.block_len;
+ DBUG_PRINT("ingo", ("Reusing block %10ld from delete link",
+ (long) *filepos));
}
else
{
@@ -418,6 +423,8 @@ static int _mi_find_writepos(MI_INFO *in
info->state->data_file_length+= tmp;
info->s->state.split++;
info->update|=HA_STATE_WRITE_AT_END;
+ DBUG_PRINT("ingo", ("Creating block %10ld new at EOF",
+ (long) *filepos));
}
DBUG_RETURN(0);
} /* _mi_find_writepos */
@@ -531,6 +538,9 @@ static int delete_dynamic_record(MI_INFO
int error;
my_bool remove_next_block;
DBUG_ENTER("delete_dynamic_record");
+ DBUG_EXECUTE("ingo", if (!second_read)
+ DBUG_PRINT("ingo", ("DELETE record %10ld",
+ (long) filepos)););
/* First add a link from the last block to the new one */
error= update_backward_delete_link(info, info->s->state.dellink, filepos);
@@ -539,6 +549,7 @@ static int delete_dynamic_record(MI_INFO
do
{
/* Remove block at 'filepos' */
+ DBUG_PRINT("ingo", ("Deleting block %10ld", (long) filepos));
if ((b_type=_mi_get_block_info(&block_info,info->dfile,filepos))
& (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
BLOCK_FATAL_ERROR) ||
@@ -555,6 +566,8 @@ static int delete_dynamic_record(MI_INFO
BLOCK_DELETED && del_block.block_len+length < MI_DYN_MAX_BLOCK_LENGTH)
{
/* We can't remove this yet as this block may be the head block */
+ DBUG_PRINT("ingo", ("Combining block %10ld with deleted block %10ld",
+ (long) filepos, (long) filepos + length));
remove_next_block=1;
length+=del_block.block_len;
}
@@ -579,6 +592,8 @@ static int delete_dynamic_record(MI_INFO
error=1;
} while (!(b_type & BLOCK_LAST));
+ DBUG_EXECUTE_IF("ingo", if (!error && !second_read)
+ debug_print_frames(info););
DBUG_RETURN(error);
}
@@ -705,6 +720,9 @@ int _mi_write_part_record(MI_INFO *info,
/* Check first if we can join this block with the next one */
MI_BLOCK_INFO del_block;
my_off_t next_block=filepos+length+extra_length+res_length;
+ DBUG_PRINT("ingo", ("Splitting block %10ld from reused block %10ld",
+ (long) filepos + length + extra_length,
+ (long) filepos));
del_block.second_read=0;
if (next_block < info->state->data_file_length &&
@@ -714,6 +732,9 @@ int _mi_write_part_record(MI_INFO *info,
& BLOCK_DELETED) &&
res_length + del_block.block_len < MI_DYN_MAX_BLOCK_LENGTH)
{
+ DBUG_PRINT("ingo",
+ ("Combining block %10ld with deleted block %10ld",
+ (long) filepos, (long) next_block));
if (unlink_deleted_block(info,&del_block))
goto err;
res_length+=del_block.block_len;
@@ -783,6 +804,8 @@ static int update_dynamic_record(MI_INFO
ulong length;
MI_BLOCK_INFO block_info;
DBUG_ENTER("update_dynamic_record");
+ DBUG_PRINT("ingo", ("UPDATE record %10ld to length: %lu",
+ (long) filepos, reclength));
flag=block_info.second_read=0;
/*
@@ -834,6 +857,8 @@ static int update_dynamic_record(MI_INFO
{
if (filepos != info->s->state.dellink)
{
+ DBUG_PRINT("ingo", ("Reusing block %10ld from old record",
+ (long) filepos));
block_info.next_filepos= HA_OFFSET_ERROR;
if ((error=_mi_get_block_info(&block_info,info->dfile,filepos))
& (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
@@ -858,7 +883,9 @@ static int update_dynamic_record(MI_INFO
info->s->base.max_data_file_length-tmp)
{
/* extend file */
- DBUG_PRINT("info",("Extending file with %d bytes",tmp));
+ DBUG_EXECUTE("ingo", if (tmp) DBUG_PRINT("ingo",
+ ("Extending block %10ld at EOF with %d bytes",
+ (long) filepos, tmp)););
if (info->nextpos == info->state->data_file_length)
info->nextpos+= tmp;
info->state->data_file_length+= tmp;
@@ -881,7 +908,10 @@ static int update_dynamic_record(MI_INFO
BLOCK_DELETED)
{
/* Use; Unlink it and extend the current block */
- DBUG_PRINT("info",("Extending current block"));
+ DBUG_PRINT("ingo",
+ ("Combining block %10ld with deleted block %10ld",
+ (long) filepos, (long) block_info.filepos +
+ block_info.block_len));
if (unlink_deleted_block(info,&del_block))
goto err;
if ((length+=del_block.block_len) > MI_MAX_BLOCK_LENGTH)
@@ -894,6 +924,8 @@ static int update_dynamic_record(MI_INFO
ulong rest_length= length-MI_MAX_BLOCK_LENGTH;
set_if_bigger(rest_length, MI_MIN_BLOCK_LENGTH);
next_pos= del_block.filepos+ del_block.block_len - rest_length;
+ DBUG_PRINT("ingo", ("Splitting block %10ld from combined block",
+ (long) next_pos));
if (update_backward_delete_link(info, info->s->state.dellink,
next_pos))
@@ -935,6 +967,7 @@ static int update_dynamic_record(MI_INFO
if (block_info.next_filepos != HA_OFFSET_ERROR)
if (delete_dynamic_record(info,block_info.next_filepos,1))
goto err;
+ DBUG_EXECUTE_IF("ingo", debug_print_frames(info););
DBUG_RETURN(0);
err:
DBUG_RETURN(1);
@@ -2004,3 +2037,260 @@ err:
my_errno=HA_ERR_WRONG_IN_RECORD; /* Garbage */
return BLOCK_ERROR;
}
+
+
+#ifndef DBUG_OFF
+/**
+ Print block-frames of a dynamic record data file.
+
+ @parameter[in] info MyISAM table object
+*/
+
+static void debug_print_frames(MI_INFO *info)
+{
+ size_t buffer_size;
+ long filepos;
+ char *buffer;
+ char *file;
+ FILE *fp= NULL;
+
+ DBUG_PRINT("ingo", ("----------"));
+
+ buffer_size= MI_MIN_BLOCK_LENGTH;
+ buffer= malloc(buffer_size);
+ if (!buffer)
+ {
+ DBUG_PRINT("ingo", ("Cannot allocate %lu bytes: %s",
+ (ulong) buffer_size, strerror(errno)));
+ goto end;
+ }
+
+ fp= fopen(info->s->data_file_name, "rb");
+ if (!fp)
+ {
+ DBUG_PRINT("ingo", ("Cannot open '%s': %s", file, strerror(errno)));
+ goto end;
+ }
+
+ filepos= 0;
+ while (fread(buffer, 1, MI_MIN_BLOCK_LENGTH, fp) == MI_MIN_BLOCK_LENGTH)
+ {
+ char *ptr;
+ const char *type;
+ uint32 rec_len;
+ uint32 data_len;
+ uint32 block_len;
+ uint32 header_len;
+ uint32 total_len;
+ uint32 read_len;
+ ulonglong next_filepos;
+ ulonglong prev_filepos;
+
+ ptr= buffer;
+ switch (*ptr)
+ {
+ case 0:
+ type= "Deleted block";
+ rec_len= 0;
+ data_len= 0;
+ block_len= mi_uint3korr(ptr + 1) - MI_MIN_BLOCK_LENGTH;
+ next_filepos= mi_uint8korr(ptr + 4);
+ prev_filepos= mi_uint8korr(ptr + 12);
+ ptr+= 20;
+ break;
+
+ case 1:
+ type= "Full small record, full";
+ rec_len= mi_uint2korr(ptr + 1);
+ data_len= rec_len;
+ block_len= data_len;
+ next_filepos= HA_OFFSET_ERROR;
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 3;
+ break;
+
+ case 2:
+ type= "Full big record, full";
+ rec_len= mi_uint3korr(ptr + 1);
+ data_len= rec_len;
+ block_len= data_len;
+ next_filepos= HA_OFFSET_ERROR;
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 4;
+ break;
+
+ case 3:
+ type= "Full small record, gap";
+ rec_len= mi_uint2korr(ptr + 1);
+ data_len= rec_len;
+ block_len= data_len + (uchar) ptr[3];
+ next_filepos= HA_OFFSET_ERROR;
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 4;
+ break;
+
+ case 4:
+ type= "Full big record, gap";
+ rec_len= mi_uint3korr(ptr + 1);
+ data_len= rec_len;
+ block_len= data_len + (uchar) ptr[4];
+ next_filepos= HA_OFFSET_ERROR;
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 5;
+ break;
+
+ case 5:
+ type= "Start small record";
+ rec_len= mi_uint2korr(ptr + 1);
+ data_len= mi_uint2korr(ptr + 3);
+ block_len= data_len;
+ next_filepos= mi_uint8korr(ptr + 5);
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 13;
+ break;
+
+ case 6:
+ type= "Start big record";
+ rec_len= mi_uint3korr(ptr + 1);
+ data_len= mi_uint3korr(ptr + 4);
+ block_len= data_len;
+ next_filepos= mi_uint8korr(ptr + 7);
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 15;
+ break;
+
+ case 7:
+ type= "End small record, full";
+ rec_len= 0;
+ data_len= mi_uint2korr(ptr + 1);
+ block_len= data_len;
+ next_filepos= HA_OFFSET_ERROR;
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 3;
+ break;
+
+ case 8:
+ type= "End big record, full";
+ rec_len= 0;
+ data_len= mi_uint3korr(ptr + 1);
+ block_len= data_len;
+ next_filepos= HA_OFFSET_ERROR;
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 4;
+ break;
+
+ case 9:
+ type= "End small record, gap";
+ rec_len= 0;
+ data_len= mi_uint2korr(ptr + 1);
+ block_len= data_len + (uchar) ptr[3];
+ next_filepos= HA_OFFSET_ERROR;
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 4;
+ break;
+
+ case 10:
+ type= "End big record, gap";
+ rec_len= 0;
+ data_len= mi_uint3korr(ptr + 1);
+ block_len= data_len + (uchar) ptr[4];
+ next_filepos= HA_OFFSET_ERROR;
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 5;
+ break;
+
+ case 11:
+ type= "Cont. small record";
+ rec_len= 0;
+ data_len= mi_uint2korr(ptr + 1);
+ block_len= data_len;
+ next_filepos= mi_uint8korr(ptr + 3);
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 11;
+ break;
+
+ case 12:
+ type= "Cont. big record";
+ rec_len= 0;
+ data_len= mi_uint3korr(ptr + 1);
+ block_len= data_len;
+ next_filepos= mi_uint8korr(ptr + 4);
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 12;
+ break;
+
+ case 13:
+ type= "Start giant record";
+ rec_len= mi_uint4korr(ptr + 1);
+ data_len= mi_uint3korr(ptr + 5);
+ block_len= data_len;
+ next_filepos= mi_uint8korr(ptr + 8);
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= 16;
+ break;
+
+ default:
+ type= "Invalid block type";
+ rec_len= 0;
+ data_len= 0;
+ block_len= 0;
+ next_filepos= HA_OFFSET_ERROR;
+ prev_filepos= HA_OFFSET_ERROR;
+ ptr+= MI_MIN_BLOCK_LENGTH;
+ break;
+
+ } /*end switch*/
+
+ header_len= ptr - buffer;
+ total_len= header_len + block_len;
+ read_len= total_len - MI_MIN_BLOCK_LENGTH;
+
+ if (*buffer)
+ DBUG_PRINT("ingo", ("%10ld %-24s block %-8u data %-8u "
+ "next %10ld rec %-8u",
+ (long) ftell(fp) - MI_MIN_BLOCK_LENGTH, type,
+ total_len, data_len, (long) next_filepos, rec_len));
+ else
+ DBUG_PRINT("ingo", ("%10ld %-24s block %-8u data %-8u "
+ "next %10ld prev %10ld",
+ (long) ftell(fp) - MI_MIN_BLOCK_LENGTH, type,
+ total_len, data_len, (long) next_filepos,
+ (long) prev_filepos));
+
+ if (total_len > buffer_size)
+ {
+ buffer_size= total_len;
+ buffer= realloc(buffer, buffer_size);
+ if (!buffer)
+ {
+ DBUG_PRINT("ingo", ("Cannot allocate %u bytes: %s",
+ buffer_size, strerror(errno)));
+ goto end;
+ }
+ }
+
+ if (fread(buffer + MI_MIN_BLOCK_LENGTH, 1, read_len, fp) != read_len)
+ {
+ DBUG_PRINT("ingo", ("Cannot read %u bytes from '%s': %s",
+ read_len, file, strerror(errno)));
+ goto end;
+ }
+
+ } /*end while*/
+
+ if (!feof(fp) && !ferror(fp))
+ DBUG_PRINT("ingo", ("Ended abnormally"));
+
+end:
+
+ if (fp && fclose(fp))
+ DBUG_PRINT("ingo", ("Cannot close data file"));
+
+ if (buffer)
+ free(buffer);
+
+ DBUG_PRINT("ingo", ("=========="));
+ DBUG_PRINT("ingo", (""));
+}
+#endif /*!DBUG_OFF*/
+
| Thread |
|---|
| • bk commit into 5.1 tree (istruewing:1.2568) BUG#36708 | Ingo Struewing | 4 Jun |