1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Backport of:

------------------------------------------------------------
revno: 2630.4.11
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w
timestamp: Tue 2008-05-27 21:31:53 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After review fixes in progress.

  Changed mysql_lock_tables() to be no longer responsible for
  reopening table if waiting for the lock on it was aborted.
  This allows to get rid of several annoying functions.


sql/ha_ndbcluster_binlog.cc:
  lock_tables() now also accepts set of options to be passed to
  mysql_lock_tables().
sql/lock.cc:
  Changed mysql_lock_tables() always requests caller to reopen
  table instead doing this on its own when waiting for lock was
  aborted. This allows us to get rid of several functions which
  were used in rare cases and significantly complicated our life.
sql/log_event_old.cc:
  lock_tables() now also accepts set of options to be passed
  to mysql_lock_tables().
sql/mysql_priv.h:
  Now mysql_lock_tables() always requests caller to reopen
  table instead doing this on its own when waiting for lock was
  aborted. So we no longer need wait_for_tables() and
  table_is_used() functions and MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN
  flag.
  open_and_lock_table_derived() and lock_tables() now accept
  options to be passed to open_tables() and mysql_lock_tables()
  calls.
sql/sql_base.cc:
  Since now mysql_lock_tables() always requests caller to
  reopen table instead doing this on its own when waiting for
  lock was aborted we no longer need wait_for_tables(),
  table_is_used() and close_old_data_files() functions.
  open_and_lock_table_derived() and lock_tables() now accept
  options to be passed to open_tables() and mysql_lock_tables()
  calls. This was needed in order to get rid of redundant code
  in open_system_tables_for_read() function.
sql/sql_handler.cc:
  mysql_lock_tables() is now always requests reopen if waiting
  for lock is aborted. MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN flag
  was removed.
sql/sql_insert.cc:
  handle_delayed_insert():
  Since mysql_lock_tables() is no longer responsible for
  reopening tables when waiting for lock was aborted we have
  to handle such situation outside of this function. To simplify
  this extracted code opening table for delayed insert thread to
  separate method of Delayed_insert class.
sql/sql_update.cc:
  lock_tables() now also accepts set of options to be passed
  to mysql_lock_tables().
This commit is contained in:
Konstantin Osipov
2009-11-30 22:03:37 +03:00
parent de1979d3d6
commit aeebede195
8 changed files with 152 additions and 283 deletions

View File

@@ -1817,6 +1817,7 @@ public:
inline uint lock_count() { return locks_in_memory; }
TABLE* get_local_table(THD* client_thd);
bool open_and_lock_table();
bool handle_inserts(void);
};
@@ -2292,6 +2293,42 @@ void kill_delayed_threads(void)
}
/**
Open and lock table for use by delayed thread and check that
this table is suitable for delayed inserts.
@retval FALSE - Success.
@retval TRUE - Failure.
*/
bool Delayed_insert::open_and_lock_table()
{
if (!(table= open_n_lock_single_table(&thd, &table_list,
TL_WRITE_DELAYED)))
{
thd.fatal_error(); // Abort waiting inserts
return TRUE;
}
if (!(table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED))
{
my_error(ER_DELAYED_NOT_SUPPORTED, MYF(ME_FATALERROR),
table_list.table_name);
return TRUE;
}
if (table->triggers)
{
/*
Table has triggers. This is not an error, but we do
not support triggers with delayed insert. Terminate the delayed
thread without an error and thus request lock upgrade.
*/
return TRUE;
}
table->copy_blobs= 1;
return FALSE;
}
/*
* Create a new delayed insert thread
*/
@@ -2354,29 +2391,8 @@ pthread_handler_t handle_delayed_insert(void *arg)
alloc_mdl_locks(&di->table_list, thd->mem_root);
/* Open table */
if (!(di->table= open_n_lock_single_table(thd, &di->table_list,
TL_WRITE_DELAYED)))
{
thd->fatal_error(); // Abort waiting inserts
if (di->open_and_lock_table())
goto err;
}
if (!(di->table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED))
{
my_error(ER_DELAYED_NOT_SUPPORTED, MYF(ME_FATALERROR),
di->table_list.table_name);
goto err;
}
if (di->table->triggers)
{
/*
Table has triggers. This is not an error, but we do
not support triggers with delayed insert. Terminate the delayed
thread without an error and thus request lock upgrade.
*/
goto err;
}
di->table->copy_blobs=1;
/* Tell client that the thread is initialized */
pthread_cond_signal(&di->cond_client);
@@ -2450,7 +2466,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
if (di->tables_in_use && ! thd->lock)
{
bool not_used;
bool need_reopen;
/*
Request for new delayed insert.
Lock the table, but avoid to be blocked by a global read lock.
@@ -2463,11 +2479,29 @@ pthread_handler_t handle_delayed_insert(void *arg)
*/
if (! (thd->lock= mysql_lock_tables(thd, &di->table, 1,
MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK,
&not_used)))
&need_reopen)))
{
/* Fatal error */
di->dead= 1;
thd->killed= THD::KILL_CONNECTION;
if (need_reopen)
{
/*
We were waiting to obtain TL_WRITE_DELAYED (probably due to
someone having or requesting TL_WRITE_ALLOW_READ) and got
aborted. Try to reopen table and if it fails die.
*/
close_thread_tables(thd);
di->table= 0;
if (di->open_and_lock_table())
{
di->dead= 1;
thd->killed= THD::KILL_CONNECTION;
}
}
else
{
/* Fatal error */
di->dead= 1;
thd->killed= THD::KILL_CONNECTION;
}
}
pthread_cond_broadcast(&di->cond_client);
}
@@ -3533,6 +3567,12 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
table->reginfo.lock_type=TL_WRITE;
hooks->prelock(&table, 1); // Call prelock hooks
/*
mysql_lock_tables() below should never fail with request to reopen table
since it won't wait for the table lock (we have exclusive metadata lock on
the table) and thus can't get aborted and since it ignores other threads
setting THD::some_tables_deleted thanks to MYSQL_LOCK_IGNORE_FLUSH.
*/
if (! ((*lock)= mysql_lock_tables(thd, &table, 1,
MYSQL_LOCK_IGNORE_FLUSH, &not_used)) ||
hooks->postlock(&table, 1))