summaryrefslogtreecommitdiff
path: root/storage/myisammrg/ha_myisammrg.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/myisammrg/ha_myisammrg.cc')
-rw-r--r--storage/myisammrg/ha_myisammrg.cc31
1 files changed, 29 insertions, 2 deletions
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index f91b0dc7a92..4d3d8362a03 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -901,7 +901,14 @@ int ha_myisammrg::external_lock(THD *thd, int lock_type)
uint ha_myisammrg::lock_count(void) const
{
- DBUG_ASSERT(this->file->children_attached);
+ /*
+ Return the real lock count even if the children are not attached.
+ This method is used for allocating memory. If we would return 0
+ to another thread (e.g. doing FLUSH TABLE), and attach the children
+ before the other thread calls store_lock(), then we would return
+ more locks in store_lock() than we claimed by lock_count(). The
+ other tread would overrun its memory.
+ */
return file->tables;
}
@@ -911,7 +918,24 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
enum thr_lock_type lock_type)
{
MYRG_TABLE *open_table;
- DBUG_ASSERT(this->file->children_attached);
+
+ /*
+ This method can be called while another thread is attaching the
+ children. If the processor reorders instructions or write to memory,
+ 'children_attached' could be set before 'open_tables' has all the
+ pointers to the children. Use of a mutex here and in
+ myrg_attach_children() forces consistent data.
+ */
+ pthread_mutex_lock(&this->file->mutex);
+
+ /*
+ When MERGE table is open, but not yet attached, other threads
+ could flush it, which means call mysql_lock_abort_for_thread()
+ on this threads TABLE. 'children_attached' is FALSE in this
+ situaton. Since the table is not locked, return no lock data.
+ */
+ if (!this->file->children_attached)
+ goto end; /* purecov: tested */
for (open_table=file->open_tables ;
open_table != file->end_table ;
@@ -921,6 +945,9 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd,
if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK)
open_table->table->lock.type=lock_type;
}
+
+ end:
+ pthread_mutex_unlock(&this->file->mutex);
return to;
}