Hi!
I've been doing a bit of digging around for an article I'm writing on
the MyISAM concurrent insert functionality and have run into a
frustrating lack of understanding on *when* exactly file locks are
placed on the .MYD data file during connection thread execution.
For the purposes of this inquiry, assume a fixed MyISAM record format,
so we'd be talking about the _mi_write_static_record() function (as tied
to the MYISAM_SHARE.write_record function pointer). If you take a look
at this stripped-down version of that function:
int _mi_write_static_record(MI_INFO *info, const uchar *record)
{
<snip>
if (info->s->state.dellink != HA_OFFSET_ERROR &&
!info->append_insert_at_end)
{
my_off_t filepos=info->s->state.dellink;
info->rec_cache.seek_not_done=1; /* We have done a seek */
if (info->s->file_read(info,(char*)
&temp[0],info->s->base.rec_reflength,
info->s->state.dellink+1,
MYF(MY_NABP)))
goto err;
info->s->state.dellink= _mi_rec_pos(info->s,temp);
info->state->del--;
info->state->empty-=info->s->base.pack_reclength;
if (info->s->file_write(info, (char*) record, info->s->base.reclength,
filepos,
MYF(MY_NABP)))
goto err;
}
else
{
<snip>
info->rec_cache.seek_not_done=1; /* We have done a seek */
if (info->s->file_write(info,(char*) record,info->s->base.reclength,
info->state->data_file_length,
info->s->write_flag))
goto err;
if (info->s->base.pack_reclength != info->s->base.reclength)
{
uint length=info->s->base.pack_reclength - info->s->base.reclength;
bzero((char*) temp,length);
if (info->s->file_write(info, (uchar*) temp,length,
info->state->data_file_length+
info->s->base.reclength,
info->s->write_flag))
goto err;
}
}
info->state->data_file_length+=info->s->base.pack_reclength;
info->s->state.split++;
}
return 0;
err:
return 1;
}
I have the following questions:
1) I notice that if the append_insert_at_end property of the share's
info struct is not set, then both a file_read() *and* a file_write() are
called when writing the data -- presumably because a seek is needed to
find the first deleted record slot...
If append_insert_at_end *is* set, then only a file_write() at the end of
the file (an append) is issued.
Is this the reason why a lock is needed when concurrent inserts aren't
enabled? In other words, does the file_read() actually lock the file
descriptor or the file in the place seeked to?
2) If file locking doesn't happen in either file_read() nor file_write()
(which I could not find any evidence that in a PREAD environment they
do...) when exactly does the file locking occur? I see that in
mi_lock_database() (in /storage/myisam/mi_locking.c) there are calls to
my_lock(), but only for the share->kfile, which I thought was just the
.frm file?
Where does the .MYD file get locked during non-concurrent inserts/writes?
Your insight would be GREATLY appreciated, as my eyesight is beginning
to blur as I grep my way through countless function pointer redirections
and redefines in /storage/myisam and /mysys
Cheers!
jay