1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +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

@ -739,4 +739,32 @@ drop table if exists t1;
create table t1 (a int) engine=innodb;
alter table t1 alter a set default 1;
drop table t1;
Bug#24918 drop table and lock / inconsistent between
perm and temp tables
Check transactional tables under LOCK TABLES
drop table if exists t24918, t24918_tmp, t24918_trans, t24918_trans_tmp,
t24918_access;
create table t24918_access (id int);
create table t24918 (id int) engine=myisam;
create temporary table t24918_tmp (id int) engine=myisam;
create table t24918_trans (id int) engine=innodb;
create temporary table t24918_trans_tmp (id int) engine=innodb;
lock table t24918 write, t24918_tmp write, t24918_trans write, t24918_trans_tmp write;
drop table t24918;
select * from t24918_access;
ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES
drop table t24918_trans;
select * from t24918_access;
ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES
drop table t24918_trans_tmp;
select * from t24918_access;
ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES
drop table t24918_tmp;
select * from t24918_access;
ERROR HY000: Table 't24918_access' was not locked with LOCK TABLES
unlock tables;
drop table t24918_access;
End of 5.0 tests