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, 2007-10-04 20:38:09+02:00, istruewing@stripped +3 -0
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Not to be pushed. For intermediate review only.
This is a technology preview for removing wait_for_tables()
from mysql_lock_tables(). Done during my Heidelberg stay.
All calls to mysql_lock_tables() do now use the flag
MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN. This means that
wait_for_tables() is not called any more.
The next step would be to remove the flag and the call
to wait_for_tables() and the function itself alltogether.
It is not used elsewhere.
Added MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN flag to mysql_lock_tables()
and added restart code where necessary.
sql/sql_base.cc@stripped, 2007-10-04 20:38:07+02:00, istruewing@stripped +29 -5
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Added MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN flag to mysql_lock_tables()
and added restart code where necessary.
sql/sql_handler.cc@stripped, 2007-10-04 20:38:07+02:00, istruewing@stripped +14 -3
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Added MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN flag to mysql_lock_tables()
and added restart code where necessary.
sql/sql_insert.cc@stripped, 2007-10-04 20:38:07+02:00, istruewing@stripped +12 -4
Bug#26379 - Combination of FLUSH TABLE and REPAIR TABLE
corrupts a MERGE table
Added MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN flag to mysql_lock_tables()
and added restart code where necessary.
diff -Nrup a/sql/sql_base.cc b/sql/sql_base.cc
--- a/sql/sql_base.cc 2007-09-12 22:11:44 +02:00
+++ b/sql/sql_base.cc 2007-10-04 20:38:07 +02:00
@@ -3194,7 +3194,8 @@ bool reopen_tables(THD *thd,bool get_loc
/* We should always get these locks */
thd->some_tables_deleted=0;
if ((lock= mysql_lock_tables(thd, tables, (uint) (tables_ptr - tables),
- 0, ¬_used)))
+ MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN,
+ ¬_used)))
{
thd->locked_tables=mysql_lock_merge(thd->locked_tables,lock);
}
@@ -4214,6 +4215,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST
thd->current_tablenr= 0;
/* open_ltable can be used only for BASIC TABLEs */
table_list->required_type= FRMTYPE_TABLE;
+ restart:
while (!(table= open_table(thd, table_list, thd->mem_root, &refresh, 0))
&&
refresh)
;
@@ -4223,10 +4225,12 @@ TABLE *open_ltable(THD *thd, TABLE_LIST
if (table->child_l)
{
/* A MERGE table must not come here. */
+ /* purecov: begin tested */
my_error(ER_WRONG_OBJECT, MYF(0), table->s->db.str,
table->s->table_name.str, "BASE TABLE");
table= 0;
goto end;
+ /* purecov: end */
}
table_list->lock_type= lock_type;
@@ -4242,8 +4246,20 @@ TABLE *open_ltable(THD *thd, TABLE_LIST
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
if (! (thd->lock= mysql_lock_tables(thd, &table_list->table, 1,
- lock_flags, &refresh)))
- table= 0;
+ lock_flags |
+ MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN,
+ &refresh)))
+ {
+ if (refresh)
+ {
+ /* This thread should have opened this table only. */
+ DBUG_ASSERT(thd->open_tables == table);
+ close_thread_table(thd, &thd->open_tables);
+ goto restart;
+ }
+ else
+ table= 0;
+ }
}
}
@@ -8070,6 +8086,7 @@ open_system_tables_for_read(THD *thd, TA
uint count= 0;
bool not_used;
+ restart:
for (TABLE_LIST *tables= table_list; tables; tables= tables->next_global)
{
TABLE *table= open_table(thd, tables, thd->mem_root, ¬_used,
@@ -8088,11 +8105,18 @@ open_system_tables_for_read(THD *thd, TA
{
TABLE **list= (TABLE**) thd->alloc(sizeof(TABLE*) * count);
TABLE **ptr= list;
+ bool refresh;
+
for (TABLE_LIST *tables= table_list; tables; tables= tables->next_global)
*(ptr++)= tables->table;
- thd->lock= mysql_lock_tables(thd, list, count,
- MYSQL_LOCK_IGNORE_FLUSH, ¬_used);
+ thd->lock= mysql_lock_tables(thd, list, count, MYSQL_LOCK_IGNORE_FLUSH |
+ MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, &refresh);
+ if (!thd->lock && refresh)
+ {
+ close_system_tables(thd, backup);
+ goto restart;
+ }
}
if (thd->lock)
DBUG_RETURN(FALSE);
diff -Nrup a/sql/sql_handler.cc b/sql/sql_handler.cc
--- a/sql/sql_handler.cc 2007-08-30 21:23:53 +02:00
+++ b/sql/sql_handler.cc 2007-10-04 20:38:07 +02:00
@@ -361,7 +361,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST
uint num_rows;
uchar *key;
uint key_len;
- bool not_used;
+ bool refresh;
DBUG_ENTER("mysql_ha_read");
DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
tables->db, tables->table_name, tables->alias));
@@ -375,6 +375,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST
List_iterator<Item> it(list);
it++;
+ restart:
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
(uchar*) tables->alias,
strlen(tables->alias) + 1)))
@@ -429,11 +430,21 @@ bool mysql_ha_read(THD *thd, TABLE_LIST
tables->table=table;
HANDLER_TABLES_HACK(thd);
- lock= mysql_lock_tables(thd, &tables->table, 1, 0, ¬_used);
+ lock= mysql_lock_tables(thd, &tables->table, 1,
+ MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, &refresh);
HANDLER_TABLES_HACK(thd);
if (!lock)
- goto err0; // mysql_lock_tables() printed error message already
+ {
+ if (refresh)
+ {
+ mysql_ha_close_table(thd, hash_tables);
+ hash_tables->table= NULL;
+ goto restart;
+ }
+ else
+ goto err0; // mysql_lock_tables() printed error message already
+ }
// Always read all columns
tables->table->read_set= &tables->table->s->all_set;
diff -Nrup a/sql/sql_insert.cc b/sql/sql_insert.cc
--- a/sql/sql_insert.cc 2007-09-12 22:11:45 +02:00
+++ b/sql/sql_insert.cc 2007-10-04 20:38:07 +02:00
@@ -1676,6 +1676,7 @@ public:
pthread_cond_t cond,cond_client;
volatile uint tables_in_use,stacked_inserts;
volatile bool status,dead;
+ bool refresh;
COPY_INFO info;
I_List<delayed_row> rows;
ulong group_count;
@@ -1844,6 +1845,7 @@ bool delayed_get_table(THD *thd, TABLE_L
/* Must be set in the parser */
DBUG_ASSERT(table_list->db);
+ restart:
/* Find the thread which handles this table. */
if (!(di= find_handler(thd, table_list)))
{
@@ -1945,6 +1947,9 @@ bool delayed_get_table(THD *thd, TABLE_L
}
/* Unlock the delayed insert object after its last access. */
di->unlock();
+ /* If mysql_lock_tables() failed, table needs refresh. */
+ if (!table_list->table && di->refresh)
+ goto restart;
DBUG_RETURN((table_list->table == NULL));
end_create:
@@ -2368,7 +2373,6 @@ pthread_handler_t handle_delayed_insert(
if (di->tables_in_use && ! thd->lock)
{
- bool not_used;
/*
Request for new delayed insert.
Lock the table, but avoid to be blocked by a global read lock.
@@ -2380,8 +2384,9 @@ pthread_handler_t handle_delayed_insert(
inserts are done.
*/
if (! (thd->lock= mysql_lock_tables(thd, &di->table, 1,
- MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK,
- ¬_used)))
+ MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK |
+ MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN,
+ &di->refresh)))
{
/* Fatal error */
di->dead= 1;
@@ -3446,8 +3451,11 @@ static TABLE *create_table_from_items(TH
{
table->reginfo.lock_type= TL_WRITE;
hooks->prelock(&table, 1); // Call prelock hooks
+ /* Locking should not fail with "need reopen". Name lock exists. */
if (! ((*lock)= mysql_lock_tables(thd, &table, 1,
- MYSQL_LOCK_IGNORE_FLUSH, ¬_used)) ||
+ MYSQL_LOCK_IGNORE_FLUSH |
+ MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN,
+ ¬_used)) ||
hooks->postlock(&table, 1))
{
if (*lock)
| Thread |
|---|
| • bk commit into 5.1 tree (istruewing:1.2610) BUG#26379 | Ingo Struewing | 4 Oct |