1
0
mirror of https://github.com/MariaDB/server.git synced 2026-01-06 05:22:24 +03:00

A fix and a test case for Bug#24918 drop table and lock / inconsistent

between perm and temp tables. Review fixes.

The original bug report complains that if we locked a temporary table
with LOCK TABLES statement, we would not leave LOCK TABLES mode
when this temporary table is dropped.

Additionally, the bug was escalated when it was discovered than
when a temporary transactional table that was previously
locked with LOCK TABLES statement was dropped, futher actions with
this table, such as UNLOCK TABLES, would lead to a crash.

The problem originates from incomplete support of transactional temporary
tables. When we added calls to handler::store_lock()/handler::external_lock()
to operations that work with such tables, we only covered the normal
server code flow and did not cover LOCK TABLES mode. 
In LOCK TABLES mode, ::external_lock(LOCK) would sometimes be called without
matching ::external_lock(UNLOCK), e.g. when a transactional temporary table
was dropped. Additionally, this table would be left in the list of LOCKed 
TABLES.

The patch aims to address this inadequacy. Now, whenever an instance
of 'handler' is destroyed, we assert that it was priorly
external_lock(UNLOCK)-ed. All the places that violate this assert
were fixed.

This patch introduces no changes in behavior -- the discrepancy in
behavior will be fixed when we start calling ::store_lock()/::external_lock()
for all tables, regardless whether they are transactional or not, 
temporary or not.


mysql-test/r/innodb_mysql.result:
  Update test results (Bug#24918)
mysql-test/t/innodb_mysql.test:
  Add a test case for Bug#24918
sql/handler.h:
  Make handler::external_lock() a protected method. Backport from 5.1 its
  public wrapper handler::ha_external_lock().
  Assert that the handler is not closed if it is still locked.
sql/lock.cc:
  In mysql_lock_tables only call lock_external() for the list of tables that
  we called store_lock() for. 
  E.g. get_lock_data() does not add non-transactional temporary tables to the
  lock list, so lock_external() should not be called for them.
  
  Use handler::ha_external_lock() instead of handler::external_lock().
  
  Add comments for mysql_lock_remove(), parameterize one strange
  side effect that it has. At least in one place where mysql_lock_remove
  is used, this side effect is not desired (DROP TABLE). The parameter
  will be dropped in 5.1, along with the side effect.
sql/mysql_priv.h:
  Update declaration of mysql_lock_remove().
sql/opt_range.cc:
  Deploy handler::ha_external_lock() instead of handler::external_lock()
sql/sql_base.cc:
  When closing a temporary table, remove the table from the list of LOCKed 
  TABLES of this thread, in case it's there. 
  It's there if it is a transactional temporary table.
  Use a new declaration of mysql_lock_remove().
sql/sql_class.h:
  Extend the comment for THD::temporary_tables.
sql/sql_table.cc:
  Deploy handler::ha_external_lock() instead of handler::external_lock()
This commit is contained in:
unknown
2007-07-27 16:37:29 +04:00
parent 2612fc43b5
commit 0936976e8d
9 changed files with 192 additions and 28 deletions

View File

@@ -995,13 +995,25 @@ enum prelocked_mode_type {NON_PRELOCKED= 0, PRELOCKED= 1,
class Open_tables_state
{
public:
/*
open_tables - list of regular tables in use by this thread
temporary_tables - list of temp tables in use by this thread
handler_tables - list of tables that were opened with HANDLER OPEN
and are still in use by this thread
/**
List of regular tables in use by this thread. Contains temporary and
base tables that were opened with @see open_tables().
*/
TABLE *open_tables, *temporary_tables, *handler_tables, *derived_tables;
TABLE *open_tables;
/**
List of temporary tables used by this thread. Contains user-level
temporary tables, created with CREATE TEMPORARY TABLE, and
internal temporary tables, created, e.g., to resolve a SELECT,
or for an intermediate table used in ALTER.
XXX Why are internal temporary tables added to this list?
*/
TABLE *temporary_tables;
/**
List of tables that were opened with HANDLER OPEN and are
still in use by this thread.
*/
TABLE *handler_tables;
TABLE *derived_tables;
/*
During a MySQL session, one can lock tables in two modes: automatic
or manual. In automatic mode all necessary tables are locked just before