1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

A post-review fix for type-aware metadata locks.

DDL no longer aborts mysql_lock_tables(), and hence
we no longer need to support need_reopen flag of this
call. 
Remove the flag, and all the code in the server
that was responsible for handling the case when
it was set. This allowed to simplify: 
open_and_lock_tables_derived(), the delayed thread,
multi-update.

Rename MYSQL_LOCK_IGNORE_FLUSH to MYSQL_OPEN_IGNORE_FLUSH,
since we now only support this flag in open_table().

Rename MYSQL_LOCK_PERF_SCHEMA to MYSQL_LOCK_LOG_TABLE,
to avoid confusion.

Move the wait for the global read lock for cases
when we do updates in SELECT f1() or DO (UPDATE) to 
open_table() from mysql_lock_tables(). When waiting
for the read lock, we could raise need_reopen flag,
which is no longer present in mysql_lock_tables().
Since the block responsible for waiting for GRL
was moved, MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK
was renamed to MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK.


mysql-test/r/mdl_sync.result:
  Update test results (see comments for mdl_sync.test).
mysql-test/t/mdl_sync.test:
  Update tests: an abort mysql_lock_tables() called for an
  INSERT no longer auto-closes SQL HANDLERS, since it
  no longer leads to back-off and retry.
sql/ha_ndbcluster_binlog.cc:
  Remove unused variables.
sql/lock.cc:
  Remove support for need_reopen parameter of mysql_lock_tables().
  Update comments.
sql/log_event_old.cc:
  Remove the loop responsible for handling need_reopen
  out parameter of mysql_lock_tables().
sql/mysql_priv.h:
  Update open and lock tables flag names.
sql/share/errmsg-utf8.txt:
  Add a new error message to report when
  thr_multi_lock() is aborted.
sql/sql_base.cc:
  Update comments. Rename MYSQL_LOCK_IGNORE_FLUSH
  to MYSQL_OPEN_IGNORE_FLUSH.
sql/sql_class.h:
  Remove unused code.
sql/sql_db.cc:
  Remove an unused bit of code.
sql/sql_handler.cc:
  For backward compatibility, we still want to back off and
  retry when a call to mysql_lock_tables() is aborted
  from within an SQL HANDLER. Write an internal error
  handler to support the case.
sql/sql_insert.cc:
  Call mysql_lock_tables() no longer has need_reopen
  out parameter. Simplify the code by removing 
  the crud that took care of it.
  MYSQL_LOCK_IGNORE_FLUSH is now only supported by
  open_tables().
sql/sql_show.cc:
  Rename MYSQL_LOCK_IGNORE_FLUSH to MYSQL_OPEN_IGNORE_FLUSH
sql/sql_table.cc:
  Remove an unused parameter.
sql/sql_update.cc:
  Remove the need_reopen loop from multi-update.
  We no also longer need to cleanup the parse tree in case
  when mysql_lock_tables() is aborted and thus an infinite
  source of multi-update bugs is gone.
sql/tztime.cc:
  Rename MYSQL_LOCK_IGNORE_FLUSH to MYSQL_OPEN_IGNORE_FLUSH,
  since from now on this flag is only supported by open_table().
This commit is contained in:
Konstantin Osipov
2010-03-16 00:20:20 +03:00
16 changed files with 255 additions and 411 deletions

View File

@ -405,6 +405,56 @@ bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
}
/**
A helper class to process an error from mysql_lock_tables().
HANDLER READ statement's attempt to lock the subject table
may get aborted if there is a pending DDL. In that case
we close the table, reopen it, and try to read again.
This is implicit and obscure, since HANDLER position
is lost in the process, but it's the legacy server
behaviour we should preserve.
*/
class Sql_handler_lock_error_handler: public Internal_error_handler
{
public:
virtual
bool handle_condition(THD *thd,
uint sql_errno,
const char *sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg,
MYSQL_ERROR **cond_hdl);
bool need_reopen() const { return m_need_reopen; };
void init() { m_need_reopen= FALSE; };
private:
bool m_need_reopen;
};
/**
Handle an error from mysql_lock_tables().
Ignore ER_LOCK_ABORTED errors.
*/
bool
Sql_handler_lock_error_handler::
handle_condition(THD *thd,
uint sql_errno,
const char *sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg,
MYSQL_ERROR **cond_hdl)
{
*cond_hdl= NULL;
if (sql_errno == ER_LOCK_ABORTED)
m_need_reopen= TRUE;
return m_need_reopen;
}
/*
Read from a HANDLER table.
@ -442,7 +492,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
uint num_rows;
uchar *UNINIT_VAR(key);
uint UNINIT_VAR(key_len);
bool need_reopen;
Sql_handler_lock_error_handler sql_handler_lock_error;
DBUG_ENTER("mysql_ha_read");
DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
tables->db, tables->table_name, tables->alias));
@ -506,8 +556,12 @@ retry:
thd->open_tables= hash_tables->table;
lock= mysql_lock_tables(thd, &thd->open_tables, 1, 0, &need_reopen);
sql_handler_lock_error.init();
thd->push_internal_handler(&sql_handler_lock_error);
lock= mysql_lock_tables(thd, &thd->open_tables, 1, 0);
thd->pop_internal_handler();
/*
In 5.1 and earlier, mysql_lock_tables() could replace the TABLE
object with another one (reopen it). This is no longer the case
@ -517,8 +571,9 @@ retry:
/* Restore previous context. */
thd->open_tables= backup_open_tables;
if (need_reopen)
if (sql_handler_lock_error.need_reopen())
{
DBUG_ASSERT(!lock && !thd->is_error());
mysql_ha_close_table(thd, hash_tables);
goto retry;
}