Commit graph

18613 commits

Author SHA1 Message Date
Konstantin Osipov
700a361a6a Backport of:
------------------------------------------------------------
 2599.161.3 Ingo Struewing      2009-07-21
 Bug#20667 - Truncate table fails for a write locked table

 TRUNCATE TABLE was not allowed under LOCK TABLES.

 The patch removes this restriction. mysql_truncate()
 does now handle that case.
2009-12-11 15:24:23 +03:00
Magne Mahre
351f28d0ce Bug#46374 crash, INSERT INTO t1 uses function, function modifies t1
An error occuring in the execution of a stored procedure, called
from do_select is masked, since the error condition is not
propagated back to the caller (join->conds->val_int() returns
a result value, and not an error code)
                  
An explicit check was added to see if the thd error code has been
set, and if so, the loop status is set to the error state.

Backport from 6.0-codebase (revid: 2617.68.31)
2009-12-10 16:22:41 +01:00
Jon Olav Hauglid
d7f9583a9b Backport of revno: 3690
Postfix for Bug#48210 FLUSH TABLES WITH READ LOCK deadlocks
                      against concurrent CREATE PROCEDURE

Rewrote the second test to use DROP PROCEDURE instead of 
CREATE USER as CREATE USER does not work with embedded server.
2009-12-10 15:09:56 +01:00
Jon Olav Hauglid
8724320989 Backport of revno: 3685
Bug #48210 FLUSH TABLES WITH READ LOCK deadlocks
           against concurrent CREATE PROCEDURE

This deadlock occured between
a) CREATE PROCEDURE (or other commands listed below)
b) FLUSH TABLES WITH READ LOCK

If the execution of them happened in the following order:
- a) opens a table (e.g. mysql.proc)
- b) locks the global read lock (or GRL)
- a) sleeps inside wait_if_global_read_lock()
- b) increases refresh_version and sleeps waiting 
     for old tables to go away

Note that a) must start waiting on the GRL before FLUSH increases
refresh_version. Otherwise a) won't wait on the GRL and instead
close its tables for reopen, allowing FLUSH to complete and thus
avoid the deadlock.

With this patch the deadlock is avoided by making CREATE PROCEDURE
acquire a protection against global read locks before it starts
executing. This means that FLUSH TABLES WITH READ LOCK will have
to wait until CREATE PROCEDURE completes before acquiring the global
read lock, thereby avoiding the deadlock.

This is implemented by introducing a new SQL command flag called
CF_PROTECT_AGAINST_GRL. Commands marked with this flag will
acquire a GRL protection in the beginning of mysql_execute_command().
This patch adds the flag to CREATE, ALTER and DROP for PROCEDURE
and FUNCTION, as well as CREATE USER, DROP USER, RENAME USER and 
REVOKE ALL. All these commands either call open_grant_tables() or
open_system_table_for_updated() which make them susceptible for
this deadlock.

The patch also adds the CF_PROTECT_AGAINST_GRL flag to a number
of commands that previously acquired GRL protection in their
respective SQLCOM case in mysql_execute_command().

Test case that checks for GRL protection for CREATE PROCEDURE
and CREATE USER added to mdl_sync.test.
2009-12-10 15:09:00 +01:00
Jon Olav Hauglid
ff0001ed57 Backport of revno: 2617.80.1
Also re-enables the test for Bug #43867

Followup to Bug#46654 False deadlock on concurrent DML/DDL with partitions, 
                      inconsistent behavior

Partition_sync.test uses features only available in debug builds.
Disabling the test for non-debug builds.
2009-12-10 14:41:41 +01:00
Jon Olav Hauglid
2945f773f2 Backport of revno: 2617.68.37
Bug #46654 False deadlock on concurrent DML/DDL with partitions, 
           inconsistent behavior

The problem was that if one connection is running a multi-statement 
transaction which involves a single partitioned table, and another 
connection attempts to alter the table, the first connection gets 
ER_LOCK_DEADLOCK and cannot proceed anymore, even when the ALTER TABLE 
statement in another connection has timed out or failed.

The reason for this was that the prepare phase for ALTER TABLE for 
partitioned tables removed all instances of the table from the table 
definition cache before it started waiting on the lock. The transaction 
running in the first connection would notice this and report ER_LOCK_DEADLOCK. 

This patch changes the prep_alter_part_table() ALTER TABLE code so that 
tdc_remove_table() is no longer called. Instead, only the TABLE instance
changed by prep_alter_part_table() is marked as needing reopen.

The patch also removes an unnecessary call to tdc_remove_table() from 
mysql_unpack_partition() as the changed TABLE object is destroyed by the 
caller at a later point.

Test case added in partition_sync.test.
2009-12-10 14:26:00 +01:00
Jon Olav Hauglid
28b0eeff28 Backport of revno: 3514
Bug#40181 Made use of tdc_remove_table instead of just 
setting share->version to 0 to make sure all unused table
instances go away as part of CREATE/ALTER TABLE.
2009-12-10 14:15:50 +01:00
Jon Olav Hauglid
1cfcd2d210 Backport of revno: 3673
Bug #47313 assert in check_key_in_view during CALL procedure

View definitions are inlined in a stored procedure when the procedure
is fist called. This means that if a temporary table is later added
with the same name as the view, the stored procedure will still
use the view. This happens even if temporary tables normally shadow
base tables/views.

The reason for the assert was that even if the stored procedure
referenced the view, open_table() still tried to open the
temporary table. This "half view/half temporary table" state
caused the assert.

The bug was not present in 5.1 as open_table() is not called
for the view there. This code was changed with the introduction 
of MDL in order to properly lock the view and any objects it 
refers to.

This patch fixes the problem by instructing open_table()
to open base tables/views (using OT_BASE_ONLY) when reopening
tables/views used by stored procedures. This also means that
a prepared statement is no longer invalidated if a temporary
table is created with the same name as a view used in the
prepared statement.

Test case added to sp.test. The test case also demonstrates
the effect of sp cache invalidation between CALLs.
2009-12-10 13:37:18 +01:00
Jon Olav Hauglid
b6fb4dbab2 Backport of revno: 2617.68.45
Bug #47635 assert in start_waiting_global_read_lock during CREATE VIEW

The problem was that CREATE VIEW would trigger an assert if
a temporary table with the same name already existed.

This bug was fixed by the patch for Bug#47335. CREATE/ALTER VIEW
will now ignore temporary tables. See Bug#47335 for more information.

Test case added to view.test.
2009-12-10 13:15:20 +01:00
Jon Olav Hauglid
3173cf335b Backport of revno: 2617.68.43
Bug #47335 assert in get_table_share

The assert would happen if ALTER VIEW was used to alter a view (existing 
or non-existing) and a temporary table with the same name already existed.

The assert is triggered if the current statement does not have a MDL lock on 
the view to be altered. This would happen because open_table() would open 
the temporary table instead and MDL locks are not taken for temporary 
tables (since they are local to one connection).

The patch changes open_type for CREATE/ALTER VIEW to OT_BASE_ONLY. This prevents 
open_table() from trying to open a temporary table with the same name should
one exist. Now the view will be altered if it exists or ER_NO_SUCH_TABLE will
be reported if it does not.

Test case added to view.test
2009-12-10 13:02:37 +01:00
Jon Olav Hauglid
9e17ef84cc Backport of revno: 2617.68.3
Followup to Bug#42546 Backup: RESTORE fails, thinking it finds an existing table

This patch updates lowercase_table2.test with the changed error message
CREATE TABLE produces if it fails because it finds an matching TABLE_SHARE 
in the TDC even if the .FRM/.MYD has been removed from disk.

With the changes introduced in Bug#42546, CREATE TABLE uses open_tables()
which will find the TDC entry and fail in open_table_from_share() with
ER_FILE_NOT_FOUND. Before, CREATE TABLE would not use open_tables() and
fail with ER_TABLE_EXISTS_ERROR upon finding the TDC entry in
mysql_create_table_no_lock().
2009-12-10 12:46:16 +01:00
Jon Olav Hauglid
b20a409c38 Backport of revno: 2617.71.1
Bug#42546 Backup: RESTORE fails, thinking it finds an existing table

The problem occured when a MDL locking conflict happened for a non-existent 
table between a CREATE and a INSERT statement. The code for CREATE 
interpreted this lock conflict to mean that the table existed, 
which meant that the statement failed when it should not have.
The problem could occur for CREATE TABLE, CREATE TABLE LIKE and
ALTER TABLE RENAME.

This patch fixes the problem for CREATE TABLE and CREATE TABLE LIKE.
It is based on code backported from the mysql-6.1-fk tree written
by Dmitry Lenev. CREATE now uses normal open_and_lock_tables() code 
to acquire exclusive locks. This means that for the test case in the bug 
description, CREATE will wait until INSERT completes so that it can 
get the exclusive lock. This resolves the reported bug.

The patch also prohibits CREATE TABLE and CREATE TABLE LIKE under 
LOCK TABLES. Note that this is an incompatible change and must 
be reflected in the documentation. Affected test cases have been
updated.

mdl_sync.test contains tests for CREATE TABLE and CREATE TABLE LIKE.

Fixing the issue for ALTER TABLE RENAME is beyond the scope of this
patch. ALTER TABLE cannot be prohibited from working under LOCK TABLES
as this could seriously impact customers and a proper fix would require
a significant rewrite.
2009-12-10 11:53:20 +01:00
Konstantin Osipov
db6864b2a7 Merge with next-4284. 2009-12-10 11:41:03 +03:00
Konstantin Osipov
2c53877895 Backport of:
------------------------------------------------------------
revno: 2617.68.10
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-next-bg46673
timestamp: Tue 2009-09-01 19:57:05 +0400
message:
  Fix for bug #46673 "Deadlock between FLUSH TABLES WITH READ LOCK and DML".

  Deadlocks occured when one concurrently executed transactions with
  several statements modifying data and FLUSH TABLES WITH READ LOCK
  statement or SET READ_ONLY=1 statement.

  These deadlocks were introduced by the patch for WL 4284: "Transactional
  DDL locking"/Bug 989: "If DROP TABLE while there's an active transaction,
  wrong binlog order" which has changed FLUSH TABLES WITH READ LOCK/SET
  READ_ONLY=1 to wait for pending transactions.
  What happened was that FLUSH TABLES WITH READ LOCK blocked all further
  statements changing tables by setting global_read_lock global variable
  and has started waiting for all pending transactions to complete.
  Then one of those transactions tried to executed DML, detected that
  global_read_lock non-zero and tried to wait until global read lock will
  be released (i.e. global_read_lock becomes 0), indeed, this led to a
  deadlock.

  Proper solution for this problem should probably involve full integration
  of global read lock with metadata locking subsystem (which will allow to
  implement waiting for pending transactions without blocking DML in them).
  But since it requires significant changes another, short-term solution
  for the problem is implemented in this patch.

  Basically, this patch restores behavior of FLUSH TABLES WITH READ LOCK/
  SET READ_ONLY=1 before the patch for WL 4284/bug 989. By ensuring that
  extra references to TABLE_SHARE are not stored for active metadata locks
  it changes these statements not to wait for pending transactions.
  As result deadlock is eliminated.
  Note that this does not change the fact that active FLUSH TABLES WITH
  READ LOCK lock or SET READ_ONLY=1 prevent modifications to tables as
  they also block transaction commits.
2009-12-09 18:56:34 +03:00
Konstantin Osipov
d8af2fe42c Backport of:
------------------------------------------------------------
revno: 2617.68.7
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-next-bg46044
timestamp: Thu 2009-08-27 10:22:17 +0400
message:
  Fix for bug #46044 "MDL deadlock on LOCK TABLE + CREATE TABLE HIGH_PRIORITY
  FOR UPDATE".

  Deadlock occured when during execution of query to I_S we tried to open
  a table or its .FRM in order to get information about it and had to wait
  because we have encountered exclusive metadata lock on this table held by
  a DDL operation from another connection which in its turn waited for some
  resource currently owned by connection executing this I_S query.
  For example, this might have happened if one under LOCK TABLES executed I_S
  query targeted to particular table (which was not among locked) and also
  concurrently tried to create this table using CREATE TABLE SELECT which
  had to wait for one of tables locked by the first connection.
  Another situation in which deadlock might have occured is when I_S query,
  which was executed as part of transaction, tried to get information about
  table which just has been dropped by concurrent DROP TABLES executed under
  LOCK TABLES and this DROP TABLES for its completion also had to wait
  transaction from the first connection.

  This problem stemmed from the fact that opening of tables/.FRMs for I_S
  filling is happening outside of connection's main MDL_context so code
  which tries to detect deadlocks due to conflicting metadata locks doesn't
  work in this case. Indeed, this led to deadlocks when during I_S filling
  we tried to wait for conflicting metadata lock to go away, while its owner
  was waiting for some resource held by connection executing I_S query.

  This patch solves this problem by avoiding waiting in such situation.
  Instead we skip this table and produce warning that information about
  it was omitted from I_S due to concurrent DDL operation. We still wait
  for conflicting metadata lock to go away when it is known that deadlock
  is not possible (i.e. when connection executing I_S query does not hold
  any metadata or table-level locks).
  Basically, we apply our standard deadlock avoidance technique for metadata
  locks to the process of filling of I_S tables but replace ER_LOCK_DEADLOCK
  error with a warning.
  Note that this change is supposed to be safe for 'mysqldump' since the
  only its mode which is affected by this change is --single-transaction mode
  is not safe in the presence of concurrent DDL anyway (and this fact is
  documented). Other modes are unaffected because they either use
  SHOW TABLES/SELECT * FROM I_S.TABLE_NAMES which do not take any metadata
  locks in the process of I_S table filling and thus cannot skip tables or
  execute I_S queries for tables which were previously locked by LOCK TABLES
  (or in the presence of global read lock) which excludes possibility of
  encountering conflicting metadata lock.
2009-12-09 18:48:42 +03:00
Jon Olav Hauglid
1b5f2b9030 Backport of revno: 2617.68.18
Bug #42147 Concurrent DML and LOCK TABLE ... READ for InnoDB 
           table cause warnings in errlog

Concurrent execution of LOCK TABLES ... READ statement and DML statements 
affecting the same InnoDB table on debug builds of MySQL server might lead 
to "Found lock of type 6 that is write and read locked" warnings appearing 
in error log.

The problem is that the table-level locking code allows a thread to acquire
TL_READ_NO_INSERT lock on a table even if there is another thread which holds 
TL_WRITE_ALLOW_WRITE lock on the same table. At the same time, the locking
code assumes that that such locks are incompatible (for example, see check_locks()).

This doesn't lead to any problems other than warnings in error log for
debug builds of server since for InnoDB tables TL_READ_NO_INSERT type of
lock is only used for LOCK TABLES and for this statement InnoDB also
performs its own table-level locking.

Unfortunately, the table lock compatibility matrix cannot be updated to disallow
TL_READ_NO_INSERT when another thread holds TL_WRITE_ALLOW_WRITE without 
causing starvation of LOCK TABLE READ in InnoDB under high write load. 
This patch therefore contains no code changes.

The issue will be fixed later when LOCK TABLE READ has been updated
to not use table locks. This bug will therefore be marked as 
"To be fixed later".

Code comment in thr_lock.c expanded to clarify the issue and a 
test case based on the bug description added to innodb_mysql_lock.test.
Note that a global suppression rule has been added to both MTR v1 and v2
for the "Found lock of type 6 that is write and read locked" warning.
These suppression rules must be removed once this bug is properly fixed.
2009-12-09 16:13:00 +01:00
lars-erik.bjork@sun.com
1642f67b40 Backport of revno: 2617.68.36
---------------------------------------------

This is a patch for bug#47098 assert in MDL_context::destroy on
HANDLER <damaged merge table> OPEN.
      
The assert occurs in MDL_context::destroy when the connection is terminated,
because all mdl_tickets have not been released.
MERGE tables do not support being opened using the HANDLER ... OPEN command,
and trying to do so will result in an error. In the event of an error, all
tables that are opened, should be closed again. The fix for bug#45781 made
sure that this also works for MERGE tables, which causes multiple tables to
be opened.
This fix extends the fix for bug#45781, by ensuring that also all locks are
released, when MERGE tables are involved.
2009-12-09 14:41:56 +01:00
Jon Olav Hauglid
cf1110cd4a Backport of revno: 3702
Bug #48248 assert in MDL_ticket::upgrade_shared_lock_to_exclusive

The assert would happen if REPAIR TABLE was used on a table already
locked by LOCK TABLES READ. REPAIR mistakenly tried to upgrade the
read-lock to exclusive, thereby triggering the assert.

The cause of the problem was that REPAIR TABLE ignored errors 
from opening and locking tables. This is by design, as REPAIR
can be used to broken tables that cannot be opened. However,
repair also ignored logical errors such as the inability to
exclusivly lock a table due to conflicting LOCK TABLES.

This patch fixes the problem by not ignoring errors from
opening and locking tables if inside LOCK TABLES mode.
In LOCK TABLES we already know that the table can be opened,
so that the failure to open must be a logical error.

Test added to repair.test.
2009-12-09 14:03:37 +01:00
Jon Olav Hauglid
20f19d147f Backport of revno: 2617.76.2
Bug #47107 assert in notify_shared_lock on incorrect CREATE TABLE , HANDLER

Attempts to create a table (using CREATE TABLE, CREATE TABLE LIKE or
CREATE TABLE SELECT statements) which already existed and was opened
by the same connection through HANDLER statement, led to a stalled
connection (for production builds of the server) or to the server being
aborted due to an assertion failure (for debug builds of the server).

This problem was introduced by the new implementation of a metadata
locking subsystem and didn't affect earlier versions of the server.

The cause of the problem was that the HANDLER was not closed by CREATE TABLE
before CREATE tried to open and lock the table. Acquiring an exclusive MDL
lock on the table to be created would therefore fail since HANDLER
already had a shared MDL lock. This triggered an assert as the 
HANDLER and CREATE statements came from the same thread (self-deadlock).

This patch resolves the issue by closing any open HANDLERs on tables
to be created by CREATE TABLE, similar to what is already done for 
DROP and ALTER TABLE.

Test case added to create.test.
2009-12-09 13:15:35 +01:00
Konstantin Osipov
346f62fbc6 Merge. 2009-12-09 12:46:13 +03:00
Konstantin Osipov
289d2bf72b Backport of:
------------------------------------------------------------
revno: 2617.69.37
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-next-bg46748
timestamp: Fri 2009-08-21 18:17:02 +0400
message:
  Fix for bug #46748 "Assertion in MDL_context::wait_for_locks()
  on INSERT + CREATE TRIGGER".

  Concurrent execution of statements involving stored functions or triggers
  which were using several tables and DDL statements which affected those
  tables on debug build of server might have led to assertion failures in
  MDL_context::wait_for_locks(). Non-debug build was not affected.

  The problem was that during back-off which happens when open_tables()
  encounters conflicting metadata lock for one of the tables being open
  we didn't reset MDL_request::ticket value for requests which correspond
  to tables from extended prelocking set. Since these requests are part
  of of list of requests to be waited for in Open_table_context this broke
  assumption that ticket value for them is 0 in MDL_context::wait_for_locks()
  and caused assertion failure.

  This fix ensures that close_tables_for_reopen(), which performs this back-off
  resets MDL_request::ticket value not only for tables directly used by the
  statement but also for tables from extended prelocking set, thus satisfying
  assumption described above.
2009-12-09 12:44:05 +03:00
Jon Olav Hauglid
e1992b3026 Backport of revno: 2617.68.39
Bug #47249 assert in MDL_global_lock::is_lock_type_compatible

This assert could be triggered if LOCK TABLES were used to lock
both a table and a view that used the same table. The table would have
to be first WRITE locked and then READ locked. So "LOCK TABLES v1
WRITE, t1 READ" would eventually trigger the assert, "LOCK TABLES
v1 READ, t1 WRITE" would not. The reason is that the ordering of locks
in the interal representation made a difference when executing 
FLUSH TABLE on the table.

During FLUSH TABLE, a lock was upgraded to exclusive. If this lock
was of type MDL_SHARED and not MDL_SHARED_UPGRADABLE, an internal
counter in the MDL subsystem would get out of sync. This would happen
if the *last* mention of the table in LOCK TABLES was a READ lock.

The counter in question is the number exclusive locks (active or intention). 
This is used to make sure a global metadata lock is only taken when the 
counter is zero (= no conflicts). The counter is increased when a
MDL_EXCLUSIVE or MDL_SHARED_UPGRADABLE lock is taken, but not when 
upgrade_shared_lock_to_exclusive() is used to upgrade directly
from MDL_SHARED to MDL_EXCLUSIVE. 

This patch fixes the problem by searching for a TABLE instance locked
with MDL_SHARED_UPGRADABLE or MDL_EXCLUSIVE before calling
upgrade_shared_lock_to_exclusive(). The patch also adds an assert checking
that only MDL_SHARED_UPGRADABLE locks are upgraded to exclusive.

Test case added to lock_multi.test.
2009-12-09 10:44:01 +01:00
Konstantin Osipov
7fa9f98667 Backport of:
------------------------------------------------------------
revno: 2617.69.32
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-next-bg46747
timestamp: Wed 2009-08-19 18:12:27 +0400
message:
  Fix for bug #46747 "Crash in MDL_ticket::upgrade_shared_lock_to_exclusive
  on TRIGGER + TEMP table".

  Server crashed when one tried to drop trigger which had its subject
  table shadowed by a temporary table with the same name.

  This problem occured because in such situation DROP TRIGGER has opened
  temporary table instead of base table on which trigger was defined.
  Attempt to upgrade metadata lock on this temporary table led to crash
  (we don't acquire metadata locks for temporary tables).

  This fix ensures that DROP TRIGGER ignores temporary tables when
  trying to open table on which trigger to be dropped is defined.
2009-12-09 12:37:54 +03:00
Konstantin Osipov
0104ea3ca0 ----------------------------------------------------------
revno: 2617.69.33
committer: Konstantin Osipov <kostja@sun.com>
branch nick: mysql-next-46452
timestamp: Wed 2009-08-19 18:39:31 +0400
message:
  Bug#46452 "Crash in MDL, HANDLER OPEN + TRUNCATE TABLE".
  Flush open HANDLER tables before TRUNCATE, which is a DDL.
2009-12-09 12:29:36 +03:00
Jon Olav Hauglid
8817b0d3af Backport of revno: 2599.169.2
Bug #42074 concurrent optimize table and 
           alter table = Assertion failed: thd->is_error()

This assertion could occur if OPTIMIZE TABLE was started on a InnoDB table
and the table was altered to different storage engine after OPTIMIZE
had started. This allowed OPTIMIZE to pass the initial checks for 
storage engine support, but fail once it reached "recreate+analyze"
if this operation was not supported by the new storage engine.
The bug had no consequences for non-debug builds of the server.

In detail, the assertion was triggered when ha_analyze() returned 
HA_ADMIN_NOT_IMPLEMENTED. This led to a code path which included an 
assert checking for diagnostics area contents. Since this area had 
not been filled, the assertion was triggered. The diagnostics area 
is in this case only used to provide more detailed information about 
why optimize failed. The triggered code path sends this information 
to the client and clears the diagnostic area.

This patch fixed the problem by adding an error message to the diagnostic 
area if ha_analyze() fails. This error message contains the error code
returned by ha_analyze().

Test case added to innodb_mysql_sync.test.
2009-12-09 09:32:29 +01:00
Jon Olav Hauglid
9e1cb3fe1b Backport of revno: 2617.68.9
Bug #43272 HANDLER SQL command does not work under LOCK TABLES

HANDLER commands are now explicitly disallowed in LOCK TABLES mode.

Before, HANDLER OPEN gave the misleading error message: "Table x was 
not locked with LOCK TABLES". This patch changes HANDLER OPEN/READ/CLOSE 
to give ER_LOCK_OR_ACTIVE_TRANSACTION "Can't execute the given command 
because you have active locked tables or an active transaction" in
LOCK TABLES mode.

Test case added to lock.test.
2009-12-08 15:56:06 +01:00
Konstantin Osipov
b9895d46c1 Merge with next-4284. 2009-12-08 16:59:54 +03:00
Konstantin Osipov
22630531cb Backport of revid 2617.69.21, 2617.69.22, 2617.29.23:
----------------------------------------------------------
revno: 2617.69.21
committer: Konstantin Osipov <kostja@sun.com>
branch nick: 5.4-4284-1-assert
timestamp: Thu 2009-08-13 20:13:55 +0400
message:
  A fix and a test case for Bug#46610 "MySQL 5.4.4: MyISAM MRG engine crash
  on auto-repair of child".
  Also fixes Bug#42862 "Crash on failed attempt to open a children of a
  merge table".

  MERGE engine needs to extend the global table list
  with TABLE_LIST elements for child tables,
  so that they are opened and locked.
  Previously these table list elements were allocated
  in memory of ha_myisammrg object (MERGE engine handler).
  That would lead to access to freed memory in
  recover_from_failed_open_table_attempt(), which would
  try to recover a MERGE table child (MyISAM table)
  and use for that TABLE_LIST of that child.
  But by the time recover_from_failed_open_table_attempt()
  is invoked, ha_myisammrg object that owns this
  TABLE_LIST may be destroyed, and thus TABLE_LIST
  memory freed.

  The fix is to ensure that TABLE_LIST elements
  that are added to the global table list (lex->query_tables)
  are always allocated in thd->mem_root, which is not
  destroyed until end of execution.

  If previously TABLE_LIST elements were allocated
  at ha_myisammrg::open() (i.e. when the TABLE
  object was created and added to the table cache),
  now they are allocated in ha_myisammrg::add_chidlren_list()
  (i.e. right after "open" of the merge parent in
  open_tables()).
  We still create a list of children names
  at ha_myisammrg::open() to use as a basis
  for creation of TABLE_LISTs, that allows
  to avoid reading the merge handler data
  file on every execution.
2009-12-08 16:57:25 +03:00
Jon Olav Hauglid
502b4ea47f Backport of revno: 2617.65.1
Bug #22876 Four-way deadlock

This bug was fixed as a part of Bug#989 
"If DROP TABLE while there's an active transaction, wrong binlog order"
A statement which would have caused circular wait will now 
be aborted with ER_LOCK_DEADLOCK.

Test case based on bug description added to innodb_mysql_lock.test.
Note that innodb_lock_wait_timeout is set to 5 mins to 
prevent race conditions in the test.
2009-12-08 14:27:33 +01:00
Jon Olav Hauglid
92ba2f2a4f Backport of revno: 2617.56.21
Bug #45066 FLUSH TABLES WITH READ LOCK deadlocks against LOCK TABLE

Test coverage for combinations of LOCK TABLE READ / WRITE and 
FLUSH TABLES / FLUSH TABLES WITH READ LOCK added to lock.test.
LOCK and FLUSH are executed sequentially from one connection.
2009-12-08 14:14:05 +01:00
Konstantin Osipov
4a8a1c568d Backport of:
----------------------------------------------------------
revno: 2617.69.2
committer: Konstantin Osipov <kostja@sun.com>
branch nick: 5.4-azalea-bugfixing
timestamp: Mon 2009-08-03 19:26:04 +0400
message:
  A fix and a test case for Bug#45035 "Altering table under LOCK TABLES
  results in "Error 1213 Deadlock found...".

  If a user had a table locked with LOCK TABLES
  for READ and for WRITE in the same connection, ALTER TABLE
  could fail.

  Root cause analysis:

  If a connection issues

  LOCK TABLE t1 write, t1 a read, t1 b read;

  the new LOCK TABLES code in 6.0 (part of WL 3726) will create
  the following list of TABLE_LIST objects
  (thd->locked_tables_list->m_locked_tables):

  {"t1" "b" tl_read_no_insert}, {"t1" "a" tl_read_no_insert},
  {"t1" "t1" tl_write }

  Later on, when we try to ALTER table t1, mysql_alter_table()
  closes all TABLE instances and releases its thr_lock locks,
  keeping only an exclusive metadata lock on t1.

  But when ALTER is finished, Locked_table_list::reopen_tables()
  tries to restore the original list of open and locked tables.

  Before this patch, it used to do so one by one:
  Open t1 b, get TL_READ_NO_INSERT lock,
  Open t1 a, get TL_READ_NO_INSERT lock
  Open t1, try to get TL_WRITE lock, deadlock.

  The cause of the deadlock is that thr_lock.c doesn't
  resolve the situation when the read list only consists
  of locks taken by the same thread, followed by this very
  thread trying to take a WRITE lock. Indeed, since
  thr_lock_multi always gets a sorted list of locks,
  WRITE locks always precede READ locks in the list
  to lock.

  Don't try to fix thr_lock.c deficiency, keep this
  code simple.
  Instead, try to take all thr_lock locks at once
  in ::reopen_tables().
2009-12-08 11:38:45 +03:00
Konstantin Osipov
90e88642af Backport of:
------------------------------------------------------------
revno: 2617.43.3
committer: Davi Arnaut <Davi.Arnaut@Sun.COM>
branch nick: 40188-6.0
timestamp: Thu 2009-05-07 13:15:54 +0200
message:
Sort results as the file list of the database directory is not
sorted (MY_DONT_SORT).

(This is a follow-up fix for WL#4284).
2009-12-08 10:53:40 +03:00
Konstantin Osipov
0b39c189ba Backport of revno ## 2617.31.1, 2617.31.3, 2617.31.4, 2617.31.5,
2617.31.12, 2617.31.15, 2617.31.15, 2617.31.16, 2617.43.1
- initial changeset that introduced the fix for 
Bug#989 and follow up fixes for all test suite failures
introduced in the initial changeset. 
------------------------------------------------------------
revno: 2617.31.1
committer: Davi Arnaut <Davi.Arnaut@Sun.COM>
branch nick: 4284-6.0
timestamp: Fri 2009-03-06 19:17:00 -0300
message:
Bug#989: If DROP TABLE while there's an active transaction, wrong binlog order
WL#4284: Transactional DDL locking

Currently the MySQL server does not keep metadata locks on
schema objects for the duration of a transaction, thus failing
to guarantee the integrity of the schema objects being used
during the transaction and to protect then from concurrent
DDL operations. This also poses a problem for replication as
a DDL operation might be replicated even thought there are
active transactions using the object being modified.

The solution is to defer the release of metadata locks until
a active transaction is either committed or rolled back. This
prevents other statements from modifying the table for the
entire duration of the transaction. This provides commitment
ordering for guaranteeing serializability across multiple
transactions.

- Incompatible change:

If MySQL's metadata locking system encounters a lock conflict,
the usual schema is to use the try and back-off technique to
avoid deadlocks -- this schema consists in releasing all locks
and trying to acquire them all in one go.

But in a transactional context this algorithm can't be utilized
as its not possible to release locks acquired during the course
of the transaction without breaking the transaction commitments.
To avoid deadlocks in this case, the ER_LOCK_DEADLOCK will be
returned if a lock conflict is encountered during a transaction.

Let's consider an example:

A transaction has two statements that modify table t1, then table
t2, and then commits. The first statement of the transaction will
acquire a shared metadata lock on table t1, and it will be kept
utill COMMIT to ensure serializability.

At the moment when the second statement attempts to acquire a
shared metadata lock on t2, a concurrent ALTER or DROP statement
might have locked t2 exclusively. The prescription of the current
locking protocol is that the acquirer of the shared lock backs off
-- gives up all his current locks and retries. This implies that
the entire multi-statement transaction has to be rolled back.

- Incompatible change:

FLUSH commands such as FLUSH PRIVILEGES and FLUSH TABLES WITH READ
LOCK won't cause locked tables to be implicitly unlocked anymore.
2009-12-05 02:02:48 +03:00
Konstantin Osipov
911c673edf Backport of:
------------------------------------------------------------
revno: 2617.23.18
committer: Davi Arnaut <Davi.Arnaut@Sun.COM>
branch nick: 4284-6.0
timestamp: Mon 2009-03-02 18:18:26 -0300
message:
Bug#989: If DROP TABLE while there's an active transaction, wrong binlog order
WL#4284: Transactional DDL locking

This is a prerequisite patch:

These changes are intended to split lock requests from granted
locks and to allow the memory and lifetime of granted locks to
be managed within the MDL subsystem. Furthermore, tickets can
now be shared and therefore are used to satisfy multiple lock
requests, but only shared locks can be recursive.

The problem is that the MDL subsystem morphs lock requests into
granted locks locks but does not manage the memory and lifetime
of lock requests, and hence, does not manage the memory of
granted locks either. This can be problematic because it puts the
burden of tracking references on the users of the subsystem and
it can't be easily done in transactional contexts where the locks
have to be kept around for the duration of a transaction.

Another issue is that recursive locks (when the context trying to
acquire a lock already holds a lock on the same object) requires
that each time the lock is granted, a unique lock request/granted
lock structure structure must be kept around until the lock is
released. This can lead to memory leaks in transactional contexts
as locks taken during the transaction should only be released at
the end of the transaction. This also leads to unnecessary wake
ups (broadcasts) in the MDL subsystem if the context still holds
a equivalent of the lock being released.

These issues are exacerbated due to the fact that WL#4284 low-level
design says that the implementation should "2) Store metadata locks
in transaction memory root, rather than statement memory root" but
this is not possible because a memory root, as implemented in mysys,
requires all objects allocated from it to be freed all at once.

This patch combines review input and significant code contributions
from Konstantin Osipov (kostja) and Dmitri Lenev (dlenev).
2009-12-04 02:29:40 +03:00
Konstantin Osipov
c44665aeb1 Backport of:
------------------------------------------------------------
revno: 3035.4.1
committer: Davi Arnaut <Davi.Arnaut@Sun.COM>
branch nick: 39897-6.0
timestamp: Thu 2009-01-15 12:17:57 -0200
message:
Bug#39897: lock_multi fails in pushbuild: timeout waiting for processlist

The problem is that relying on the "Table lock" thread state in
its current position to detect that a thread is waiting on a lock
is race prone. The "Table lock" state change happens before the
thread actually tries to grab a lock on a table.

The solution is to move the "Table lock" state so that its set
only when a thread is actually going to wait for a lock. The state
change happens after the thread fails to grab the lock (because it
is owned by other thread) and proceeds to wait on a condition.

This is considered part of work related to WL#4284 "Transactional
DDL locking"
Warning: this patch contains an incompatible change. 
When waiting on a lock in thr_lock.c, the server used to display "Locked"
processlist state. After this patch, the state is "Table lock".
The new state was actually intended to be display since year 2002,
when Monty added it. But up until removal of thd->locked boolean
member, this state was ignored by SHOW PROCESSLIST code.
2009-12-03 23:08:27 +03:00
Konstantin Osipov
3a8a750919 Backport of:
------------------------------------------------------------
revno: 2630.13.17
committer: Davi Arnaut <Davi.Arnaut@Sun.COM>
branch nick: 4284-6.0
timestamp: Sun 2008-07-27 10:14:46 -0300
message:
Post-merge fixes:

Remove dependency on binlog, require not embedded as test uses
the event scheduler and disable abort on error for syntax only
available on servers built with debugging support.

This is a patch in scope of WL#4284 "Transactional DDL locking"
2009-12-03 18:52:21 +03:00
Konstantin Osipov
4ae05129dc Backport of:
------------------------------------------------------------
revno: 2630.13.16
committer: Davi Arnaut <Davi.Arnaut@Sun.COM>
branch nick: WL#4284
timestamp: Sat 2008-07-26 13:38:20 -0300
message:
WL#4284: Transactional DDL locking

SQL statements' effect on transactions.

Currently the MySQL server and its storage engines are not
capable of rolling back operations that define or modify data
structures (also known as DDL statements) or operations that
alter any of the system tables (the mysql database). Allowing
these group of statements to participate in transactions
is unfeasible at this time (since rollback has no effect
whatsoever on them) and goes against the design of our metadata
locking subsystem.

The solution is to issue implicit commits before and after
those statements execution. This effectively confines each of
those statements to its own special transaction and ensures
that metadata locks taken during this special transaction
are not leaked into posterior statements/transactions.
2009-12-03 18:47:20 +03:00
Konstantin Osipov
d64cf75806 Merge next-mr -> next-4284 2009-12-03 14:37:42 +03:00
Konstantin Osipov
485cac3963 Merge next-mr -> next-mr-runtime 2009-12-03 14:01:04 +03:00
Konstantin Osipov
ef15a335b3 Backport of:
----------------------------------------------------------
revno: 2630.4.38
committer: Konstantin Osipov <konstantin@mysql.com>
branch nick: mysql-6.0-4144
timestamp: Wed 2008-06-25 22:07:06 +0400
message:
  WL#4144 - Lock MERGE engine children.
  Committing a version of the patch merged with WL#3726
  on behalf of Ingo.

  Step #1: Move locking from parent to children.

  MERGE children are now left in the query list of tables
  after inserted there in open_tables(). So they are locked
  by lock_tables() as all other tables are.

  The MERGE parent does not store locks any more. It appears
  in a MYSQL_LOCK with zero lock data. This is kind of a "dummy"
  lock.

  All other lock handling is also done directly on the children.
  To protect against parent or child modifications during LOCK
  TABLES, the children are detached after every statement and
  attached before every statement, even under LOCK TABLES.

  The children table list is removed from the query list of tables
  on every detach and on close of the parent.

  Step #2: Move MERGE specific functionality from SQL layer
  into table handler.

  Functionality moved from SQL layer (mainly sql_base.cc)
  to the table handler (ha_myisammrg.cc).

  Unnecessary code is removed from the SQL layer.

  Step #3: Moved all MERGE specific members from TABLE
  to ha_myisammrg.

  Moved members from TABLE to ha_myisammrg.
  Renamed some mebers.
  Fixed comments.

  Step #4: Valgrind and coverage testing

  Valgrind did not uncover new problems.
  Added purecov comments.

  Added a new test for DATA/INDEX DIRECTORY options.
  Changed handling of ::reset() for non-attached children.
  Fixed the merge-big test.

  Step #5: Fixed crashes detected during review
  Changed detection when to attach/detach.
  Added new tests.

Backport also the fix for Bug#44040 "MySQL allows creating a 
MERGE table upon VIEWs but crashes when using it"
2009-12-03 02:09:22 +03:00
Konstantin Osipov
416a626368 Backport of:
----------------------------------------------------------
revno: 2630.4.35
committer: Konstantin Osipov <konstantin@mysql.com>
branch nick: mysql-6.0-3726
timestamp: Wed 2008-06-25 16:44:00 +0400
message:
  Fix a MyISAM-specific bug in the new implementation of
  LOCK TABLES (WL#3726).
  If more than one instance of a MyISAM table are open in the
  same connection, all of them must share the same status_param.
  Otherwise, unlock of a table may lead to lost records.
  See also comments in thr_lock.c.
2009-12-02 23:47:23 +03:00
Alexander Nozdrin
3f797a46de Auto-merge from mysql-next-mr. 2009-12-02 19:00:26 +03:00
Konstantin Osipov
bcae0d9bab Backport of:
----------------------------------------------------------
revno: 2630.10.1
committer: Konstantin Osipov <konstantin@mysql.com>
branch nick: mysql-6.0-lock-tables-tidyup
timestamp: Wed 2008-06-11 15:49:58 +0400
message:
  WL#3726, review fixes.
  Now that we have metadata locks, we don't need to keep a crippled
  TABLE instance in the table cache to indicate that a table is locked.
  Remove all code that used this technique. Instead, rely on metadata
  locks and use the standard open_table() and close_thread_table()
  to manipulate with the table cache tables.
  Removes a list of functions that have become unused (see the comment
  for sql_base.cc for details).
  Under LOCK TABLES, keep a TABLE_LIST instance for each table
  that may be temporarily closed. For that, implement an own class for
  LOCK TABLES mode, Locked_tables_list.

This is a pre-requisite patch for WL#4144.
This is not exactly a backport: there is no new 
online ALTER table in Celosia, so the old alter table
code was changed to work with the new table cache API.
2009-12-02 18:22:15 +03:00
Konstantin Osipov
cf4a4ba6fd Backport of:
------------------------------------------------------------
revno: 2630.9.3
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w3
timestamp: Wed 2008-06-11 08:33:36 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After review fixes in progress.

  Changed close_cached_tables() not to flush all unused TABLE
  instances when flushing individual table.
  Renamed expel_table_from_cache() to tdc_remove_table() and
  added enum parameter to be able more explicitly specify type
  of removal, rewrote its code to be more efficient.

******
Backport of:
------------------------------------------------------------
revno: 2630.9.4
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w3
timestamp: Wed 2008-06-11 15:53:53 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After-review fixes in progress.

  Minor changes in order to improve code readability
  and simplify debugging.
2009-12-01 22:13:01 +03:00
Andrei Elkin
e8e85ed2a6 Manual resolving for the following files
Text conflict in mysql-test/collections/default.experimental
Text conflict in mysql-test/r/show_check.result
Text conflict in mysql-test/r/sp-code.result
Text conflict in mysql-test/suite/binlog/r/binlog_tmp_table.result
Text conflict in mysql-test/suite/rpl/t/disabled.def
Text conflict in mysql-test/t/show_check.test
Text conflict in mysys/my_delete.c
Text conflict in sql/item.h
Text conflict in sql/item_cmpfunc.h
Text conflict in sql/log.cc
Text conflict in sql/mysqld.cc
Text conflict in sql/repl_failsafe.cc
Text conflict in sql/slave.cc
Text conflict in sql/sql_parse.cc
Text conflict in sql/sql_table.cc
Text conflict in sql/sql_yacc.yy
Text conflict in storage/myisam/ha_myisam.cc

Corrected results for
 stm_auto_increment_bug33029.reject      2009-12-01
		20:01:49.000000000 +0300
       <andrei> @@ -42,9 +42,6 @@
       <andrei>  RETURN i;
       <andrei>  END//
       <andrei>  CALL p1();
       <andrei> -Warnings:
       <andrei> -Note   1592    Statement may not be safe to log in statement
		format.
       <andrei> -Note   1592    Statement may not be safe to log in statement
		format.

There should be indeed no Note present because there is in fact autoincrement 
top-level query in sp() that triggers inserting in yet another auto-inc table.
(todo: alert DaoGang to improve the test).
2009-12-01 21:07:18 +02:00
Konstantin Osipov
076722c4af Backport of:
----------------------------------------------------------------
2630.4.9 Dmitry Lenev	2008-05-26
         WL#3726 "DDL locking for all metadata objects".
        
         After review fixes in progress. Adjusted test case
         according to review.
2009-11-30 19:21:40 +03:00
Konstantin Osipov
b2ac2b8b1d Backport of:
------------------------------------------------------------
revno: 2630.4.7
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w
timestamp: Sun 2008-05-25 11:19:02 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  Fixed silly mistake in test case which caused sporadic
  kill.test failures.
2009-11-30 19:09:42 +03:00
Konstantin Osipov
69b9761f29 Initial import of WL#3726 "DDL locking for all metadata objects".
Backport of:
------------------------------------------------------------
revno: 2630.4.1
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w
timestamp: Fri 2008-05-23 17:54:03 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After review fixes in progress.
------------------------------------------------------------

This is the first patch in series. It transforms the metadata 
locking subsystem to use a dedicated module (mdl.h,cc). No 
significant changes in the locking protocol. 
The import passes the test suite with the exception of 
deprecated/removed 6.0 features, and MERGE tables. The latter
are subject to a fix by WL#4144.
Unfortunately, the original changeset comments got lost in a merge,
thus this import has its own (largely insufficient) comments.

This patch fixes Bug#25144 "replication / binlog with view breaks".
Warning: this patch introduces an incompatible change:
Under LOCK TABLES, it's no longer possible to FLUSH a table that 
was not locked for WRITE.
Under LOCK TABLES, it's no longer possible to DROP a table or
VIEW that was not locked for WRITE.

******
Backport of:
------------------------------------------------------------
revno: 2630.4.2
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w
timestamp: Sat 2008-05-24 14:03:45 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After review fixes in progress.

******
Backport of:
------------------------------------------------------------
revno: 2630.4.3
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w
timestamp: Sat 2008-05-24 14:08:51 +0400
message:
  WL#3726 "DDL locking for all metadata objects"

  Fixed failing Windows builds by adding mdl.cc to the lists
  of files needed to build server/libmysqld on Windows.

******
Backport of:
------------------------------------------------------------
revno: 2630.4.4
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w
timestamp: Sat 2008-05-24 21:57:58 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  Fix for assert failures in kill.test which occured when one
  tried to kill ALTER TABLE statement on merge table while it
  was waiting in wait_while_table_is_used() for other connections
  to close this table.

  These assert failures stemmed from the fact that cleanup code
  in this case assumed that temporary table representing new
  version of table was open with adding to THD::temporary_tables
  list while code which were opening this temporary table wasn't
  always fulfilling this.

  This patch changes code that opens new version of table to
  always do this linking in. It also streamlines cleanup process
  for cases when error occurs while we have new version of table
  open.

******
WL#3726 "DDL locking for all metadata objects"
Add libmysqld/mdl.cc to .bzrignore.
******
Backport of:
------------------------------------------------------------
revno: 2630.4.6
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w
timestamp: Sun 2008-05-25 00:33:22 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  Addition to the fix of assert failures in kill.test caused by
  changes for this worklog.


Make sure we close the new table only once.
2009-11-30 18:55:03 +03:00
Andrei Elkin
a6f2076c03 merging from 5.1 to rep+2 starting at gca(5.1, next-mr) == build@mysql.com-20091104182209-iui387z35159aoyw 2009-11-30 14:34:39 +02:00
Horst.Hunger
a6d408c3cd another patch to fix differences. 2009-11-27 13:08:38 +01:00