Commit graph

234 commits

Author SHA1 Message Date
Dmitry Lenev
6bf6272fda Patch that refactors global read lock implementation and fixes
bug #57006 "Deadlock between HANDLER and FLUSH TABLES WITH READ
LOCK" and bug #54673 "It takes too long to get readlock for
'FLUSH TABLES WITH READ LOCK'".

The first bug manifested itself as a deadlock which occurred
when a connection, which had some table open through HANDLER
statement, tried to update some data through DML statement
while another connection tried to execute FLUSH TABLES WITH
READ LOCK concurrently.

What happened was that FTWRL in the second connection managed
to perform first step of GRL acquisition and thus blocked all
upcoming DML. After that it started to wait for table open
through HANDLER statement to be flushed. When the first connection
tried to execute DML it has started to wait for GRL/the second
connection creating deadlock.

The second bug manifested itself as starvation of FLUSH TABLES
WITH READ LOCK statements in cases when there was a constant
stream of concurrent DML statements (in two or more
connections).

This has happened because requests for protection against GRL
which were acquired by DML statements were ignoring presence of
pending GRL and thus the latter was starved.

This patch solves both these problems by re-implementing GRL
using metadata locks.

Similar to the old implementation acquisition of GRL in new
implementation is two-step. During the first step we block
all concurrent DML and DDL statements by acquiring global S
metadata lock (each DML and DDL statement acquires global IX
lock for its duration). During the second step we block commits
by acquiring global S lock in COMMIT namespace (commit code
acquires global IX lock in this namespace).

Note that unlike in old implementation acquisition of
protection against GRL in DML and DDL is semi-automatic.
We assume that any statement which should be blocked by GRL
will either open and acquires write-lock on tables or acquires
metadata locks on objects it is going to modify. For any such
statement global IX metadata lock is automatically acquired
for its duration.

The first problem is solved because waits for GRL become
visible to deadlock detector in metadata locking subsystem
and thus deadlocks like one in the first bug become impossible.

The second problem is solved because global S locks which
are used for GRL implementation are given preference over
IX locks which are acquired by concurrent DML (and we can
switch to fair scheduling in future if needed).

Important change:
FTWRL/GRL no longer blocks DML and DDL on temporary tables.
Before this patch behavior was not consistent in this respect:
in some cases DML/DDL statements on temporary tables were
blocked while in others they were not. Since the main use cases
for FTWRL are various forms of backups and temporary tables are
not preserved during backups we have opted for consistently
allowing DML/DDL on temporary tables during FTWRL/GRL.

Important change:
This patch changes thread state names which are used when
DML/DDL of FTWRL is waiting for global read lock. It is now
either "Waiting for global read lock" or "Waiting for commit
lock" depending on the stage on which FTWRL is.

Incompatible change:
To solve deadlock in events code which was exposed by this
patch we have to replace LOCK_event_metadata mutex with
metadata locks on events. As result we have to prohibit
DDL on events under LOCK TABLES.

This patch also adds extensive test coverage for interaction
of DML/DDL and FTWRL.

Performance of new and old global read lock implementations
in sysbench tests were compared. There were no significant
difference between new and old implementations.

mysql-test/include/check_ftwrl_compatible.inc:
  Added helper script which allows to check that a statement is
  compatible with FLUSH TABLES WITH READ LOCK.
mysql-test/include/check_ftwrl_incompatible.inc:
  Added helper script which allows to check that a statement is
  incompatible with FLUSH TABLES WITH READ LOCK.
mysql-test/include/handler.inc:
  Adjusted test case to the fact that now DROP TABLE closes
  open HANDLERs for the table to be dropped before checking
  if there active FTWRL in this connection.
mysql-test/include/wait_show_condition.inc:
  Fixed small error in the timeout message. The correct name
  of variable used as parameter for this script is "$condition"
  and not "$wait_condition".
mysql-test/r/delayed.result:
  Added test coverage for scenario which triggered assert in
  metadata locking subsystem.
mysql-test/r/events_2.result:
  Updated test results after prohibiting event DDL operations
  under LOCK TABLES.
mysql-test/r/flush.result:
  Added test coverage for bug #57006 "Deadlock between HANDLER
  and FLUSH TABLES WITH READ LOCK".
mysql-test/r/flush_read_lock.result:
  Added test coverage for various aspects of FLUSH TABLES WITH
  READ LOCK functionality.
mysql-test/r/flush_read_lock_kill.result:
  Adjusted test case after replacing custom global read lock
  implementation with one based on metadata locks. Use new
  debug_sync point. Do not disable concurrent inserts as now
  InnoDB we always use InnoDB table.
mysql-test/r/handler_innodb.result:
  Adjusted test case to the fact that now DROP TABLE closes
  open HANDLERs for the table to be dropped before checking
  if there active FTWRL in this connection.
mysql-test/r/handler_myisam.result:
  Adjusted test case to the fact that now DROP TABLE closes
  open HANDLERs for the table to be dropped before checking
  if there active FTWRL in this connection.
mysql-test/r/mdl_sync.result:
  Adjusted test case after replacing custom global read lock
  implementation with one based on metadata locks. Replaced
  usage of GRL-specific debug_sync's with appropriate sync
  points in MDL subsystem.
mysql-test/suite/perfschema/r/dml_setup_instruments.result:
  Updated test results after removing global
  COND_global_read_lock condition variable.
mysql-test/suite/perfschema/r/func_file_io.result:
  Ensure that this test doesn't affect subsequent tests.
  At the end of its execution enable back P_S instrumentation
  which this test disables at some point.
mysql-test/suite/perfschema/r/func_mutex.result:
  Ensure that this test doesn't affect subsequent tests.
  At the end of its execution enable back P_S instrumentation
  which this test disables at some point.
mysql-test/suite/perfschema/r/global_read_lock.result:
  Adjusted test case to take into account that new GRL
  implementation is based on MDL.
mysql-test/suite/perfschema/r/server_init.result:
  Adjusted test case after replacing custom global read
  lock implementation with one based on MDL and replacing
  LOCK_event_metadata mutex with metadata lock.
mysql-test/suite/perfschema/t/func_file_io.test:
  Ensure that this test doesn't affect subsequent tests.
  At the end of its execution enable back P_S instrumentation
  which this test disables at some point.
mysql-test/suite/perfschema/t/func_mutex.test:
  Ensure that this test doesn't affect subsequent tests.
  At the end of its execution enable back P_S instrumentation
  which this test disables at some point.
mysql-test/suite/perfschema/t/global_read_lock.test:
  Adjusted test case to take into account that new GRL
  implementation is based on MDL.
mysql-test/suite/perfschema/t/server_init.test:
  Adjusted test case after replacing custom global read
  lock implementation with one based on MDL and replacing
  LOCK_event_metadata mutex with metadata lock.
mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result:
  Updated test results after prohibiting event DDL under
  LOCK TABLES.
mysql-test/t/delayed.test:
  Added test coverage for scenario which triggered assert in
  metadata locking subsystem.
mysql-test/t/events_2.test:
  Updated test case after prohibiting event DDL operations
  under LOCK TABLES.
mysql-test/t/flush.test:
  Added test coverage for bug #57006 "Deadlock between HANDLER
  and FLUSH TABLES WITH READ LOCK".
mysql-test/t/flush_block_commit.test:
  Adjusted test case after changing thread state name which
  is used when COMMIT waits for FLUSH TABLES WITH READ LOCK
  from "Waiting for release of readlock" to "Waiting for commit
  lock".
mysql-test/t/flush_block_commit_notembedded.test:
  Adjusted test case after changing thread state name which is
  used when DML waits for FLUSH TABLES WITH READ LOCK. Now we
  use "Waiting for global read lock" in this case.
mysql-test/t/flush_read_lock.test:
  Added test coverage for various aspects of FLUSH TABLES WITH
  READ LOCK functionality.
mysql-test/t/flush_read_lock_kill-master.opt:
  We no longer need to use make_global_read_lock_block_commit_loop
  debug tag in this test. Instead we rely on an appropriate
  debug_sync point in MDL code.
mysql-test/t/flush_read_lock_kill.test:
  Adjusted test case after replacing custom global read lock
  implementation with one based on metadata locks. Use new
  debug_sync point. Do not disable concurrent inserts as now
  InnoDB we always use InnoDB table.
mysql-test/t/lock_multi.test:
  Adjusted test case after changing thread state names which
  are used when DML or DDL waits for FLUSH TABLES WITH READ
  LOCK to "Waiting for global read lock".
mysql-test/t/mdl_sync.test:
  Adjusted test case after replacing custom global read lock
  implementation with one based on metadata locks. Replaced
  usage of GRL-specific debug_sync's with appropriate sync
  points in MDL subsystem. Updated thread state names which
  are used when DDL waits for FTWRL.
mysql-test/t/trigger_notembedded.test:
  Adjusted test case after changing thread state names which
  are used when DML or DDL waits for FLUSH TABLES WITH READ
  LOCK to "Waiting for global read lock".
sql/event_data_objects.cc:
  Removed Event_queue_element::status/last_executed_changed
  members and Event_queue_element::update_timing_fields()
  method. We no longer use this class for updating mysql.events
  once event is chosen for execution. Accesses to instances of
  this class in scheduler thread require protection by
  Event_queue::LOCK_event_queue mutex and we try to avoid
  updating table while holding this lock.
sql/event_data_objects.h:
  Removed Event_queue_element::status/last_executed_changed
  members and Event_queue_element::update_timing_fields()
  method. We no longer use this class for updating mysql.events
  once event is chosen for execution. Accesses to instances of
  this class in scheduler thread require protection by
  Event_queue::LOCK_event_queue mutex and we try to avoid
  updating table while holding this lock.
sql/event_db_repository.cc:
  - Changed Event_db_repository methods to not release all
    metadata locks once they are done updating mysql.events
    table. This allows to keep metadata lock protecting
    against GRL and lock protecting particular event around
    until corresponding DDL statement is written to the binary
    log.
  - Removed logic for conditional update of "status" and
    "last_executed" fields from update_timing_fields_for_event()
    method. In the only case when this method is called now
    "last_executed" is always modified and tracking change
    of "status" is too much hassle.
sql/event_db_repository.h:
  Removed logic for conditional update of "status" and
  "last_executed" fields from Event_db_repository::
  update_timing_fields_for_event() method.
  In the only case when this method is called now "last_executed"
  is always modified and tracking change of "status" field is
  too much hassle.
sql/event_queue.cc:
  Changed event scheduler code not to update mysql.events
  table while holding Event_queue::LOCK_event_queue mutex.
  Doing so led to a deadlock with a new GRL implementation.
  This deadlock didn't occur with old implementation due to
  fact that code acquiring protection against GRL ignored
  pending GRL requests (which lead to GRL starvation).
  One of goals of new implementation is to disallow GRL
  starvation and so we have to solve problem with this
  deadlock in a different way.
sql/events.cc:
  Changed methods of Events class to acquire protection
  against GRL while perfoming DDL statement and keep it
  until statement is written to the binary log.
  Unfortunately this step together with new GRL implementation
  exposed deadlock involving Events::LOCK_event_metadata
  and GRL. To solve it Events::LOCK_event_metadata mutex was
  replaced with a metadata lock on event. As a side-effect
  events DDL has to be prohibited under LOCK TABLES even in
  cases when mysql.events table was explicitly locked for
  write.
sql/events.h:
  Replaced Events::LOCK_event_metadata mutex with a metadata
  lock on event.
sql/ha_ndbcluster.cc:
  Updated code after replacing custom global read lock
  implementation with one based on MDL. Since MDL subsystem
  should now be able to detect deadlocks involving metadata
  locks and GRL there is no need for special handling of
  active GRL.
sql/handler.cc:
  Replaced custom implementation of global read lock with
  one based on metadata locks. Consequently when doing
  commit instead of calling method of Global_read_lock
  class to acquire protection against GRL we simply acquire
  IX in COMMIT namespace.
sql/lock.cc:
  Replaced custom implementation of global read lock with
  one based on metadata locks. This step allows to expose
  wait for GRL to deadlock detector of MDL subsystem and
  thus succesfully resolve deadlocks similar to one behind
  bug #57006 "Deadlock between HANDLER and FLUSH TABLES
  WITH READ LOCK". It also solves problem with GRL starvation
  described in bug #54673 "It takes too long to get readlock
  for 'FLUSH TABLES WITH READ LOCK'" since metadata locks used
  by GRL give preference to FTWRL statement instead of DML
  statements (if needed in future this can be changed to
  fair scheduling).
  
  Similar to old implementation of acquisition of GRL is
  two-step. During the first step we block all concurrent
  DML and DDL statements by acquiring global S metadata lock
  (each DML and DDL statement acquires global IX lock for
  its duration). During the second step we block commits by
  acquiring global S lock in COMMIT namespace (commit code
  acquires global IX lock in this namespace).
  
  Note that unlike in old implementation acquisition of
  protection against GRL in DML and DDL is semi-automatic.
  We assume that any statement which should be blocked by GRL
  will either open and acquires write-lock on tables or acquires
  metadata locks on objects it is going to modify. For any such
  statement global IX metadata lock is automatically acquired
  for its duration.
  
  To support this change:
  - Global_read_lock::lock/unlock_global_read_lock and
    make_global_read_lock_block_commit methods were changed
    accordingly.
  - Global_read_lock::wait_if_global_read_lock() and
    start_waiting_global_read_lock() methods were dropped.
    It is now responsibility of code acquiring metadata locks
    opening tables to acquire protection against GRL by
    explicitly taking global IX lock with statement duration.
  - Global variables, mutex and condition variable used by
    old implementation was removed.
  - lock_routine_name() was changed to use statement duration for
    its global IX lock. It was also renamed to lock_object_name()
    as it now also used to take metadata locks on events.
  - Global_read_lock::set_explicit_lock_duration() was added which
    allows not to release locks used for GRL when leaving prelocked
    mode.
sql/lock.h:
  - Renamed lock_routine_name() to lock_object_name() and changed
    its signature to allow its usage for events.
  - Removed broadcast_refresh() function. It is no longer needed
    with new GRL implementation.
sql/log_event.cc:
  Release metadata locks with statement duration at the end
  of processing legacy event for LOAD DATA. This ensures that
  replication thread processing such event properly releases
  its protection against global read lock.
sql/mdl.cc:
  Changed MDL subsystem to support new MDL-based implementation
  of global read lock.
  
  Added COMMIT and EVENTS namespaces for metadata locks. Changed
  thread state name for GLOBAL namespace to "Waiting for global
  read lock".
  
  Optimized MDL_map::find_or_insert() method to avoid taking
  m_mutex mutex when looking up MDL_lock objects for GLOBAL
  or COMMIT namespaces. We keep pre-created MDL_lock objects
  for these namespaces around and simply return pointers to
  these global objects when needed.
  
  Changed MDL_lock/MDL_scoped_lock to properly handle
  notification of insert delayed handler threads when FTWRL
  takes global S lock.
  
  Introduced concept of lock duration. In addition to locks with
  transaction duration which work in the way which is similar to
  how locks worked before (i.e. they are released at the end of
  transaction), locks with statement and explicit duration were
  introduced.
  Locks with statement duration are automatically released at the
  end of statement. Locks with explicit duration require explicit
  release and obsolete concept of transactional sentinel.
  
  * Changed MDL_request and MDL_ticket classes to support notion
    of duration.
  * Changed MDL_context to keep locks with different duration in
    different lists. Changed code handling ticket list to take
    this into account.
  * Changed methods responsible for releasing locks to take into
    account duration of tickets. Particularly public
    MDL_context::release_lock() method now only can release
    tickets with explicit duration (there is still internal
    method which allows to specify duration). To release locks
    with statement or transaction duration one have to use
    release_statement/transactional_locks() methods.
  * Concept of savepoint for MDL subsystem now has to take into
    account locks with statement duration. Consequently
    MDL_savepoint class was introduced and methods working with
    savepoints were updated accordingly.
  * Added methods which allow to set duration for one or all
    locks in the context.
sql/mdl.h:
  Changed MDL subsystem to support new MDL-based implementation
  of global read lock.
  
  Added COMMIT and EVENTS namespaces for metadata locks.
  
  Introduced concept of lock duration. In addition to locks with
  transaction duration which work in the way which is similar to
  how locks worked before (i.e. they are released at the end of
  transaction), locks with statement and explicit duration were
  introduced.
  Locks with statement duration are automatically released at the
  end of statement. Locks with explicit duration require explicit
  release and obsolete concept of transactional sentinel.
  
  * Changed MDL_request and MDL_ticket classes to support notion
    of duration.
  * Changed MDL_context to keep locks with different duration in
    different lists. Changed code handling ticket list to take
    this into account.
  * Changed methods responsible for releasing locks to take into
    account duration of tickets. Particularly public
    MDL_context::release_lock() method now only can release
    tickets with explicit duration (there is still internal
    method which allows to specify duration). To release locks
    with statement or transaction duration one have to use
    release_statement/transactional_locks() methods.
  * Concept of savepoint for MDL subsystem now has to take into
    account locks with statement duration. Consequently
    MDL_savepoint class was introduced and methods working with
    savepoints were updated accordingly.
  * Added methods which allow to set duration for one or all
    locks in the context.
sql/mysqld.cc:
  Removed global mutex and condition variables which were used
  by old implementation of GRL.
  Also we no longer need to initialize Events::LOCK_event_metadata
  mutex as it was replaced with metadata locks on events.
sql/mysqld.h:
  Removed global variable, mutex and condition variables which
  were used by old implementation of GRL.
sql/rpl_rli.cc:
  When slave thread closes tables which were open for handling
  of RBR events ensure that it releases global IX lock which
  was acquired as protection against GRL.
sql/sp.cc:
  Adjusted code to the new signature of lock_object/routine_name(),
  to the fact that one now needs specify duration of lock when
  initializing MDL_request and to the fact that savepoints for MDL
  subsystem are now represented by MDL_savepoint class.
sql/sp_head.cc:
  Ensure that statements in stored procedures release statement
  metadata locks and thus release their protectiong against GRL
  in proper moment in time.
  Adjusted code to the fact that one now needs specify duration
  of lock when initializing MDL_request.
sql/sql_admin.cc:
  Adjusted code to the fact that one now needs specify duration
  of lock when initializing MDL_request.
sql/sql_base.cc:
  - Implemented support for new approach to acquiring protection
    against global read lock. We no longer acquire such protection
    explicitly on the basis of statement flags. Instead we always
    rely on code which is responsible for acquiring metadata locks
    on object to be changed acquiring this protection. This is
    achieved by acquiring global IX metadata lock with statement
    duration. Code doing this also responsible for checking that
    current connection has no active GRL by calling an
    Global_read_lock::can_acquire_protection() method.
    Changed code in open_table() and lock_table_names()
    accordingly.
    Note that as result of this change DDL and DML on temporary
    tables is always compatible with GRL (before it was
    incompatible in some cases and compatible in other cases).
  - To speed-up code acquiring protection against GRL introduced
    m_has_protection_against_grl member in Open_table_context
    class. It indicates that protection was already acquired
    sometime during open_tables() execution and new attempts
    can be skipped.
  - Thanks to new GRL implementation calls to broadcast_refresh()
    became unnecessary and were removed.
  - Adjusted code to the fact that one now needs specify duration
    of lock when initializing MDL_request and to the fact that
    savepoints for MDL subsystem are now represented by
    MDL_savepoint class.
sql/sql_base.h:
  Adjusted code to the fact that savepoints for MDL subsystem are
  now represented by MDL_savepoint class.
  Also introduced Open_table_context::m_has_protection_against_grl
  member which allows to avoid acquiring protection against GRL
  while opening tables if such protection was already acquired.
sql/sql_class.cc:
  Changed THD::leave_locked_tables_mode() after transactional
  sentinel for metadata locks was obsoleted by introduction of
  locks with explicit duration.
sql/sql_class.h:
  - Adjusted code to the fact that savepoints for MDL subsystem
    are now represented by MDL_savepoint class.
  - Changed Global_read_lock class according to changes in
    global read lock implementation:
    * wait_if_global_read_lock and start_waiting_global_read_lock
      are now gone. Instead code needing protection against GRL
      has to acquire global IX metadata lock with statement
      duration itself. To help it new can_acquire_protection()
      was introduced. Also as result of the above change
      m_protection_count member is gone too.
    * Added m_mdl_blocks_commits_lock member to store metadata
      lock blocking commits.
    * Adjusted code to the fact that concept of transactional
      sentinel was obsoleted by concept of lock duration.
  - Removed CF_PROTECT_AGAINST_GRL flag as it is no longer
    necessary. New GRL implementation acquires protection
    against global read lock automagically when statement
    acquires metadata locks on tables or other objects it
    is going to change.
sql/sql_db.cc:
  Adjusted code to the fact that one now needs specify duration
  of lock when initializing MDL_request.
sql/sql_handler.cc:
  Removed call to broadcast_refresh() function. It is no longer
  needed with new GRL implementation.
  Adjusted code after introducing duration concept for metadata
  locks. Particularly to the fact transactional sentinel was
  replaced with explicit duration.
sql/sql_handler.h:
  Renamed mysql_ha_move_tickets_after_trans_sentinel() to
  mysql_ha_set_explicit_lock_duration() after transactional
  sentinel was obsoleted by locks with explicit duration.
sql/sql_insert.cc:
  Adjusted code handling delaying inserts after switching to
  new GRL implementation. Now connection thread initiating
  delayed insert has to acquire global IX lock in addition
  to metadata lock on table being inserted into. This IX lock
  protects against GRL and similarly to SW lock on table being
  inserted into has to be passed to handler thread in order to
  avoid deadlocks.
sql/sql_lex.cc:
  LEX::protect_against_global_read_lock member is no longer
  necessary since protection against GRL is automatically
  taken by code acquiring metadata locks/opening tables.
sql/sql_lex.h:
  LEX::protect_against_global_read_lock member is no longer
  necessary since protection against GRL is automatically
  taken by code acquiring metadata locks/opening tables.
sql/sql_parse.cc:
  - Implemented support for new approach to acquiring protection
    against global read lock. We no longer acquire such protection
    explicitly on the basis of statement flags. Instead we always
    rely on code which is responsible for acquiring metadata locks
    on object to be changed acquiring this protection. This is
    achieved by acquiring global IX metadata lock with statement
    duration. This lock is automatically released at the end of
    statement execution.
  - Changed implementation of CREATE/DROP PROCEDURE/FUNCTION not
    to release metadata locks and thus protection against of GRL
    in the middle of statement execution.
  - Adjusted code to the fact that one now needs specify duration
    of lock when initializing MDL_request and to the fact that
    savepoints for MDL subsystem are now represented by
    MDL_savepoint class.
sql/sql_prepare.cc:
  Adjusted code to the to the fact that savepoints for MDL
  subsystem are now represented by MDL_savepoint class.
sql/sql_rename.cc:
  With new GRL implementation there is no need to explicitly
  acquire protection against GRL before renaming tables.
  This happens automatically in code which acquires metadata
  locks on tables being renamed.
sql/sql_show.cc:
  Adjusted code to the fact that one now needs specify duration
  of lock when initializing MDL_request and to the fact that
  savepoints for MDL subsystem are now represented by
  MDL_savepoint class.
sql/sql_table.cc:
  - With new GRL implementation there is no need to explicitly
    acquire protection against GRL before dropping tables.
    This happens automatically in code which acquires metadata
    locks on tables being dropped.
  - Changed mysql_alter_table() not to release lock on new table
    name explicitly and to rely on automatic release of locks
    at the end of statement instead. This was necessary since
    now MDL_context::release_lock() is supported only for locks
    for explicit duration.
sql/sql_trigger.cc:
  With new GRL implementation there is no need to explicitly
  acquire protection against GRL before changing table triggers.
  This happens automatically in code which acquires metadata
  locks on tables which triggers are to be changed.
sql/sql_update.cc:
  Fix bug exposed by GRL testing. During prepare phase acquire
  only S metadata locks instead of SW locks to keep prepare of
  multi-UPDATE compatible with concurrent LOCK TABLES WRITE
  and global read lock.
sql/sql_view.cc:
  With new GRL implementation there is no need to explicitly
  acquire protection against GRL before creating view.
  This happens automatically in code which acquires metadata
  lock on view to be created.
sql/sql_yacc.yy:
  LEX::protect_against_global_read_lock member is no longer
  necessary since protection against GRL is automatically
  taken by code acquiring metadata locks/opening tables.
sql/table.cc:
  Adjusted code to the fact that one now needs specify duration
  of lock when initializing MDL_request.
sql/table.h:
  Adjusted code to the fact that one now needs specify duration
  of lock when initializing MDL_request.
sql/transaction.cc:
  Replaced custom implementation of global read lock with
  one based on metadata locks. Consequently when doing
  commit instead of calling method of Global_read_lock
  class to acquire protection against GRL we simply acquire
  IX in COMMIT namespace.
  Also adjusted code to the fact that MDL savepoint is now
  represented by MDL_savepoint class.
2010-11-11 20:11:05 +03:00
Konstantin Osipov
29c4873ad5 Commit on behalf of Dmitry Lenev.
Merge his patch for Bug#52044 into 5.5, and apply 
review comments.
2010-08-12 17:50:23 +04:00
Konstantin Osipov
36290c0923 A pre-requisite patch for the fix for Bug#52044.
This patch also fixes Bug#55452 "SET PASSWORD is
replicated twice in RBR mode".

The goal of this patch is to remove the release of 
metadata locks from close_thread_tables().
This is necessary to not mistakenly release
the locks in the course of a multi-step
operation that involves multiple close_thread_tables()
or close_tables_for_reopen().

On the same token, move statement commit outside 
close_thread_tables().

Other cleanups:
Cleanup COM_FIELD_LIST.
Don't call close_thread_tables() in COM_SHUTDOWN -- there
are no open tables there that can be closed (we leave
the locked tables mode in THD destructor, and this
close_thread_tables() won't leave it anyway).

Make open_and_lock_tables() and open_and_lock_tables_derived()
call close_thread_tables() upon failure.
Remove the calls to close_thread_tables() that are now
unnecessary.

Simplify the back off condition in Open_table_context.

Streamline metadata lock handling in LOCK TABLES 
implementation.

Add asserts to ensure correct life cycle of 
statement transaction in a session.

Remove a piece of dead code that has also become redundant
after the fix for Bug 37521.

mysql-test/r/variables.result:
  Update results: set @@autocommit and statement transaction/
  prelocked mode.
mysql-test/r/view.result:
  A harmless change in CHECK TABLE <view> status for a broken view.
  If previously a failure to prelock all functions used in a view 
  would leave the connection in LTM_PRELOCKED mode, now we call
  close_thread_tables() from open_and_lock_tables()
  and leave prelocked mode, thus some check in mysql_admin_table() that
  works only in prelocked/locked tables mode is no longer activated.
mysql-test/suite/rpl/r/rpl_row_implicit_commit_binlog.result:
  Fixed Bug#55452 "SET PASSWORD is replicated twice in
  RBR mode": extra binlog events are gone from the
  binary log.
mysql-test/t/variables.test:
  Add a test case: set autocommit and statement transaction/prelocked
  mode.
sql/event_data_objects.cc:
  Simplify code in Event_job_data::execute().
  Move sp_head memory management to lex_end().
sql/event_db_repository.cc:
  Move the release of metadata locks outside
  close_thread_tables().
  Make sure we call close_thread_tables() when
  open_and_lock_tables() fails and remove extra
  code from the events data dictionary.
  Use close_mysql_tables(), a new internal
  function to properly close mysql.* tables
  in the data dictionary.
  Contract Event_db_repository::drop_events_by_field,
  drop_schema_events into one function.
  When dropping all events in a schema,
  make sure we don't mistakenly release all
  locks acquired by DROP DATABASE. These
  include locks on the database name
  and the global intention exclusive
  metadata lock.
sql/event_db_repository.h:
  Function open_event_table() does not require an instance 
  of Event_db_repository.
sql/events.cc:
  Use close_mysql_tables() instead of close_thread_tables()
  to bootstrap events, since the latter no longer
  releases metadata locks.
sql/ha_ndbcluster.cc:
  - mysql_rm_table_part2 no longer releases
  acquired metadata locks. Do it in the caller.
sql/ha_ndbcluster_binlog.cc:
  Deploy the new protocol for closing thread
  tables in run_query() and ndb_binlog_index
  code.
sql/handler.cc:
  Assert that we never call ha_commit_trans/
  ha_rollback_trans in sub-statement, which
  is now the case.
sql/handler.h:
  Add an accessor to check whether THD_TRANS object
  is empty (has no transaction started).
sql/log.cc:
  Update a comment.
sql/log_event.cc:
  Since now we commit/rollback statement transaction in 
  mysql_execute_command(), we need a mechanism to communicate
  from Query_log_event::do_apply_event() to mysql_execute_command()
  that the statement transaction should be rolled back, not committed.
  Ideally it would be a virtual method of THD. I hesitate
  to make THD a virtual base class in this already large patch.
  Use a thd->variables.option_bits for now.
  
  Remove a call to close_thread_tables() from the slave IO
  thread. It doesn't open any tables, and the protocol
  for closing thread tables is more complicated now.
  
  Make sure we properly close thread tables, however, 
  in Load_data_log_event, which doesn't
  follow the standard server execution procedure
  with mysql_execute_command().
  @todo: this piece should use Server_runnable
  framework instead.
  Remove an unnecessary call to mysql_unlock_tables().
sql/rpl_rli.cc:
  Update Relay_log_info::slave_close_thread_tables()
  to follow the new close protocol.
sql/set_var.cc:
  Remove an unused header.
sql/slave.cc:
  Remove an unnecessary call to
  close_thread_tables().
sql/sp.cc:
  Remove unnecessary calls to close_thread_tables()
  from SP DDL implementation. The tables will
  be closed by the caller, in mysql_execute_command().
  When dropping all routines in a database, make sure
  to not mistakenly drop all metadata locks acquired
  so far, they include the scoped lock on the schema.
sql/sp_head.cc:
  Correct the protocol that closes thread tables
  in an SP instruction.
  Clear lex->sphead before cleaning up lex
  with lex_end to make sure that we don't
  delete the sphead twice. It's considered
  to be "cleaner" and more in line with
  future changes than calling delete lex->sphead
  in other places that cleanup the lex.
sql/sp_head.h:
  When destroying m_lex_keeper of an instruction,
  don't delete the sphead that all lex objects
  share. 
  @todo: don't store a reference to routine's sp_head
  instance in instruction's lex.
sql/sql_acl.cc:
  Don't call close_thread_tables() where the caller will
  do that for us.
  Fix Bug#55452 "SET PASSWORD is replicated twice in RBR 
  mode" by disabling RBR replication in change_password()
  function.
  Use close_mysql_tables() in bootstrap and ACL reload
  code to make sure we release all metadata locks.
sql/sql_base.cc:
  This is the main part of the patch:
  - remove manipulation with thd->transaction
  and thd->mdl_context from close_thread_tables().
  Now this function is only responsible for closing
  tables, nothing else.
  This is necessary to be able to easily use
  close_thread_tables() in procedures, that
  involve multiple open/close tables, which all
  need to be protected continuously by metadata
  locks.
  Add asserts ensuring that TABLE object
  is only used when is protected by a metadata lock.
  Simplify the back off condition of Open_table_context,
  we no longer need to look at the autocommit mode.
  Make open_and_lock_tables() and open_normal_and_derived_tables()
  close thread tables and release metadata locks acquired so-far 
  upon failure. This simplifies their usage.
  Implement close_mysql_tables().
sql/sql_base.h:
  Add declaration for close_mysql_tables().
sql/sql_class.cc:
  Remove a piece of dead code that has also become redundant
  after the fix for Bug 37521.
  The code became dead when my_eof() was made a non-protocol method,
  but a method that merely modifies the diagnostics area.
  The code became redundant with the fix for Bug#37521, when 
  we started to cal close_thread_tables() before
  Protocol::end_statement().
sql/sql_do.cc:
  Do nothing in DO if inside a substatement
  (the assert moved out of trans_rollback_stmt).
sql/sql_handler.cc:
  Add comments.
sql/sql_insert.cc:
  Remove dead code. 
  Release metadata locks explicitly at the
  end of the delayed insert thread.
sql/sql_lex.cc:
  Add destruction of lex->sphead to lex_end(),
  lex "reset" method called at the end of each statement.
sql/sql_parse.cc:
  Move close_thread_tables() and other related
  cleanups to mysql_execute_command()
  from dispatch_command(). This has become
  possible after the fix for Bug#37521.
  Mark federated SERVER statements as DDL.
  
  Next step: make sure that we don't store
  eof packet in the query cache, and move
  the query cache code outside mysql_parse.
  
  Brush up the code of COM_FIELD_LIST.
  Remove unnecessary calls to close_thread_tables().
  
  When killing a query, don't report "OK"
  if it was a suicide.
sql/sql_parse.h:
  Remove declaration of a function that is now static.
sql/sql_partition.cc:
  Remove an unnecessary call to close_thread_tables().
sql/sql_plugin.cc:
  open_and_lock_tables() will clean up
  after itself after a failure.
  Move close_thread_tables() above
  end: label, and replace with close_mysql_tables(),
  which will also release the metadata lock
  on mysql.plugin.
sql/sql_prepare.cc:
  Now that we no longer release locks in close_thread_tables()
  statement prepare code has become more straightforward.
  Remove the now redundant check for thd->killed() (used
  only by the backup project) from Execute_server_runnable.
  Reorder code to take into account that now mysql_execute_command()
  performs lex->unit.cleanup() and close_thread_tables().
sql/sql_priv.h:
  Add a new option to server options to interact
  between the slave SQL thread and execution
  framework (hack). @todo: use a virtual
  method of class THD instead.
sql/sql_servers.cc:
  Due to Bug 25705 replication of 
  DROP/CREATE/ALTER SERVER is broken.
  Make sure at least we do not attempt to 
  replicate these statements using RBR,
  as this violates the assert in close_mysql_tables().
sql/sql_table.cc:
  Do not release metadata locks in mysql_rm_table_part2,
  this is done by the caller.
  Do not call close_thread_tables() in mysql_create_table(),
  this is done by the caller. 
  Fix a bug in DROP TABLE under LOCK TABLES when,
  upon error in wait_while_table_is_used() we would mistakenly
  release the metadata lock on a non-dropped table.
  Explicitly release metadata locks when doing an implicit
  commit.
sql/sql_trigger.cc:
  Now that we delete lex->sphead in lex_end(),
  zero the trigger's sphead in lex after loading
  the trigger, to avoid double deletion.
sql/sql_udf.cc:
  Use close_mysql_tables() instead of close_thread_tables().
sql/sys_vars.cc:
  Remove code added in scope of WL#4284 which would
  break when we perform set @@session.autocommit along
  with setting other variables and using tables or functions.
  A test case added to variables.test.
sql/transaction.cc:
  Add asserts.
sql/tztime.cc:
  Use close_mysql_tables() rather than close_thread_tables().
2010-07-27 14:25:53 +04:00
Jon Olav Hauglid
f45523188e merge from mysql-trunk-bugfixing 2010-07-13 10:39:24 +02:00
Davi Arnaut
f56dd32bf7 Bug#34043: Server loops excessively in _checkchunk() when safemalloc is enabled
Essentially, the problem is that safemalloc is excruciatingly
slow as it checks all allocated blocks for overrun at each
memory management primitive, yielding a almost exponential
slowdown for the memory management functions (malloc, realloc,
free). The overrun check basically consists of verifying some
bytes of a block for certain magic keys, which catches some
simple forms of overrun. Another minor problem is violation
of aliasing rules and that its own internal list of blocks
is prone to corruption.

Another issue with safemalloc is rather the maintenance cost
as the tool has a significant impact on the server code.
Given the magnitude of memory debuggers available nowadays,
especially those that are provided with the platform malloc
implementation, maintenance of a in-house and largely obsolete
memory debugger becomes a burden that is not worth the effort
due to its slowness and lack of support for detecting more
common forms of heap corruption.

Since there are third-party tools that can provide the same
functionality at a lower or comparable performance cost, the
solution is to simply remove safemalloc. Third-party tools
can provide the same functionality at a lower or comparable
performance cost. 

The removal of safemalloc also allows a simplification of the
malloc wrappers, removing quite a bit of kludge: redefinition
of my_malloc, my_free and the removal of the unused second
argument of my_free. Since free() always check whether the
supplied pointer is null, redudant checks are also removed.

Also, this patch adds unit testing for my_malloc and moves
my_realloc implementation into the same file as the other
memory allocation primitives.

client/mysqldump.c:
  Pass my_free directly as its signature is compatible with the
  callback type -- which wasn't the case for free_table_ent.
2010-07-08 18:20:08 -03:00
Jon Olav Hauglid
132ccf93d8 Bug #54401 assert in Diagnostics_area::set_eof_status , HANDLER
This assert checks that the server does not try to send EOF to the
client if there has been some error during processing. This to make
sure that the error is in fact sent to the client.

The problem was that any errors during processing of WHERE conditions
in HANDLER ... READ statements where not detected by the handler code.
The handler code therefore still tried to send EOF to the client,
triggering the assert. The bug was only noticeable in debug builds.

This patch fixes the problem by making sure that the handler code
checks for errors during condition processing and acts accordingly.
2010-07-05 13:59:34 +02:00
Konstantin Osipov
cc6dabba37 Merge trunk-bugfixing -> trunk-runtime 2010-06-17 17:31:51 +04:00
Ramil Kalimullin
3844367f2b Automerge. 2010-06-11 19:36:57 +04:00
Ramil Kalimullin
f4b7c50d6e Fix for bug #54007: assert in ha_myisam::index_next, HANDLER
Problem: the server missed the fact that one can read from 
2 indexes alternately using HANDLER interface.

Fix: check if the same (initialized) index is involved
reading next/prev values from the index.


mysql-test/r/handler_myisam.result:
  Fix for bug #54007: assert in ha_myisam::index_next, HANDLER
    - test result.
mysql-test/t/handler_myisam.test:
  Fix for bug #54007: assert in ha_myisam::index_next, HANDLER
    - test case.
sql/sql_handler.cc:
  Fix for bug #54007: assert in ha_myisam::index_next, HANDLER
    - check if we use the same (initialized) index 
  to read next/prev values from the index.
2010-06-09 14:45:04 +04:00
Konstantin Osipov
8d42534182 A review comment for WL#4441 " LOCK_open: Remove requirement of
mutex protecting thd->open_tables".

We should not manipulate with table->s->version outside the 
table definition cache code, but use the TDC API
to achieve the desired result.

Fix one violation: close_all_tables_for_name().

sql/sql_base.cc:
  Use tdc_remove_table(TDC_RT_REMOVE_ALL) to expel the
  table share in close_all_tables_for_name, rather
  than manipulate with the table cache explicitly.
  
  Make sure that close_cached_tables() calls 
  close_all_tables_for_name() after closing all the involved
  handlers. The rest of the code was inspected to
  make sure that mysql_ha_rm_tables() is called.
sql/sql_handler.cc:
  Add a method to close all HANDLER cursors for a list
  of tables.
sql/sql_handler.h:
  Add declaration for mysql_ha_flush_tables().
2010-06-09 12:39:09 +04:00
Konstantin Osipov
d4f1abaad2 WL#4441 "LOCK_open: Remove requirement of mutex protecting
thd->open_tables"

thd->open_tables list is not normally accessed concurrently
except for one case: when the connection has open SQL
HANDLER tables, and we want to perform a DDL on the table,
we want to abort waits on MyISAM thr_lock of those connections
that prevent the DDL from proceeding, and iterate
over thd->open_tables list to find out the tables on which
the thread is waiting.

In 5.5 we mostly use deadlock detection and soft deadlock 
prevention, as opposed to "hard" deadlock prevention
of 5.1, which would abort any transaction that
may cause a deadlock. The only remaining case when
neither deadlock detection nor deadlock prevention
is implemented in 5.5 is HANDLER SQL, where we use
old good thr_lock_abort() technique form 5.1. 

Thus, replace use of LOCK_open to protect thd->open_tables
with thd->LOCK_ha_data (a lock protecting various session
private data).

This is a port of the work done for 5.5.4 for review
and inclusion into 5.5.5.

sql/sql_base.cc:
  Use thd->LOCK_ha_data (systematically) to set
  thd->open_tables.
sql/sql_class.h:
  Implement THD::set_open_tables().
sql/sql_cursor.cc:
  Use thd->LOCK_ha_data (systematically) to set
  thd->open_tables.
sql/sql_handler.cc:
  Use thd->LOCK_ha_data (systematically) to set
  thd->open_tables.
  Acquisition of LOCK_open is moved inside close_thread_table().
sql/sql_table.cc:
  Acquisition of LOCK_open is moved inside close_thread_tables().
2010-06-08 12:08:46 +04:00
Mats Kindahl
23d8586dbf WL#5030: Split and remove mysql_priv.h
This patch:

- Moves all definitions from the mysql_priv.h file into
  header files for the component where the variable is
  defined
- Creates header files if the component lacks one
- Eliminates all include directives from mysql_priv.h
- Eliminates all circular include cycles
- Rename time.cc to sql_time.cc
- Rename mysql_priv.h to sql_priv.h
2010-03-31 16:05:33 +02:00
Konstantin Osipov
09b7a0d115 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().
2010-03-16 00:20:20 +03:00
Konstantin Osipov
7116431a8a A review comment for the fix for Bug#46672.
Remove unnecessary need_reopen loops.
2010-03-13 13:58:27 +03:00
Jon Olav Hauglid
3f1a9baf0b Bug #51355 handler stmt cause assertion in
bool MDL_context::try_acquire_lock(MDL_request*)

This assert was triggered in the following way:
1) HANDLER OPEN t1 from connection 1
2) DROP TABLE t1 from connection 2. This will block due to the metadata lock
held by the open handler in connection 1.
3) DML statement (e.g. INSERT) from connection 1. This will close the table
opened by the HANDLER in 1) and release its metadata lock. This is done due
to the pending exclusive metadata lock from 2). 
4) DROP TABLE t1 from connection 2 now completes and removes table t1.
5) HANDLER READ from connection 1. Since the handler table was closed in 3),
the handler code will try to reopen the table. First a new metadata lock on
t1 will be granted before the command fails since the table was removed in 4).
6) HANDLER READ from connection 1. This caused the assert.

The reason for the assert was that the MDL_request's pointer to the lock
ticket was not reset when the statement failed. HANDLER READ then tried to
acquire a lock using the same MDL_request object, triggering the assert.
This bug was only noticeable on debug builds and did not cause any problems
on release builds.

This patch fixes the problem by assuring that the pointer to the metadata 
lock ticket is reset when reopening of handler tables fails.

Test case added to handler.inc
2010-02-25 18:08:12 +01:00
Dmitry Lenev
d5a498abc6 Fix for bug #50908 "Assertion `handler_tables_hash.records == 0'
failed in enter_locked_tables_mode".

Server was aborted due to assertion failure when one tried to 
execute statement requiring prelocking (i.e. firing triggers
or using stored functions) while having open HANDLERs.

The problem was that THD::enter_locked_tables_mode() method
which was called at the beginning of execution of prelocked 
statement assumed there are no open HANDLERs. It had to do 
so because corresponding THD::leave_locked_tables_mode()
method was unable to properly restore MDL sentinel when
leaving LOCK TABLES/prelocked mode in the presence of open 
HANDLERs.

This patch solves this problem by changing the latter method
to properly restore MDL sentinel and thus removing need for 
this assumption. As a side-effect, it lifts unjustified
limitation by allowing to keep HANDLERs open when entering 
LOCK TABLES mode.

mysql-test/include/handler.inc:
  Adjusted tests after making LOCK TABLES not to close
  open HANDLERs. Added coverage for bug #50908
  "Assertion `handler_tables_hash.records == 0' failed
  in enter_locked_tables_mode".
mysql-test/r/handler_innodb.result:
  Updated test results (see include/handler.inc).
mysql-test/r/handler_myisam.result:
  Updated test results (see include/handler.inc).
sql/mysql_priv.h:
  Introduced mysql_ha_move_tickets_after_trans_sentinel()
  routine which allows to move tickets for metadata locks
  corresponding to open HANDLERs after transaction sentinel.
sql/sql_class.cc:
  Changed THD::leave_locked_tables_mode() to correctly restore 
  MDL sentinel value in the presence of open HANDLERs.
sql/sql_class.h:
  Removed assert from THD::enter_locked_tables_mode() as we
  no longer have to close HANDLERs when entering LOCK TABLES 
  or prelocked modes. Instead we keep them open and correctly
  restore MDL sentinel value after leaving them.
  Removal of assert also fixes problem from the bug report.
sql/sql_handler.cc:
  Introduced mysql_ha_move_tickets_after_trans_sentinel()
  routine which allows to move tickets for metadata locks
  corresponding to open HANDLERs after transaction sentinel.
sql/sql_parse.cc:
  We no longer have to close HANDLERs when entering LOCK TABLES 
  mode. Instead we keep them open and simply correctly restore 
  MDL sentinel value after leaving this mode.
2010-02-12 10:05:43 +03:00
Dmitry Lenev
8018ec5adb Fix for bug #50913 "Deadlock between open_and_lock_tables_derived
and MDL".

Concurrent execution of a multi-DELETE statement and ALTER
TABLE statement which affected one of the tables used in
the multi-DELETE sometimes led to deadlock.
Similar deadlocks might have occured when one performed
INSERT/UPDATE/DELETE on a view and concurrently executed
ALTER TABLE for the view's underlying table, or when one
concurrently executed TRUNCATE TABLE for InnoDB table and
ALTER TABLE for the same table.

These deadlocks were caused by a discrepancy between types of
metadata and thr_lock.cc locks acquired by those statements.

What happened was that multi-DELETE/TRUNCATE/DML-through-the-
view statement in the first connection acquired SR lock on a
table, then ALTER TABLE would come in in the second connection
and acquire SNW metadata lock and TL_WRITE_ALLOW_READ
thr_lock.c lock and then would start waiting for the first
connection during lock upgrade. After that the statement in
the first connection would try to acquire TL_WRITE lock on
table and would start waiting for the second connection,
creating a deadlock.

This patch solves this problem by ensuring that we acquire
SW metadata lock in all cases in which we acquiring write
thr_lock.c lock. This guarantees that deadlocks like the
one described above won't occur since all lock conflicts
in such situation are resolved within MDL subsystem.

This patch also adds assert which should guarantee that
such situations won't arise in future.

mysql-test/r/lock_multi.result:
  Added main test for bug #50913 "Deadlock between
  open_and_lock_tables_derived and MDL".
mysql-test/r/mdl_sync.result:
  Added additional coverage for bug #50913 "Deadlock
  between open_and_lock_tables_derived and MDL".
mysql-test/t/lock_multi.test:
  Added main test for bug #50913 "Deadlock between
  open_and_lock_tables_derived and MDL".
mysql-test/t/mdl_sync.test:
  Added additional coverage for bug #50913 "Deadlock
  between open_and_lock_tables_derived and MDL".
sql/lock.cc:
  Added assert that enforces that when we are locking
  a non-temporary table we have an appropriate type of
  metadata lock on this table.
sql/mysql_priv.h:
  Added separate flag for open_tables() to be able specify that
  SH metadata locks on table to be open should be acquired.
  We can no longer use MYSQL_LOCK_IGNORE_FLUSH flag for this
  as in addition to use in I_S implementation it is also used
  for opening system tables. Since in the latter case we also
  acquire thr_lock.c locks using SH metadata lock in it instead
  of SR or SW locks may lead to deadlock.
sql/sql_base.cc:
  When opening tables don't interpret MYSQL_LOCK_IGNORE_FLUSH
  flag as request to acquire SH metadata locks. This flag is
  also used for opening system tables for which we also take
  thr_lock.c locks and thus proper metadata lock to take in
  this case is SR or SW lock (otherwise deadlocks can occur).
  In cases when SH lock is really required (e.g. when tables
  are open by I_S implementation) we rely on that newly
  introduced MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL flag is
  used.
sql/sql_delete.cc:
  mysql_truncate_by_delete():
    Adjust type of metadata lock to be requested after changing
    type of thr_lock.c lock for table list element from one
    which was set in parser to TL_WRITE.
    This removes discrepancy between types of these locks which
    allowed deadlocks to creep in.
sql/sql_handler.cc:
  When closing table which was open by HANDLER statement clear
  TABLE::open_by_handler flag. This allows to use this flag as
  a reliable indication that TABLE instance was open by HANDLER
  statement in assert which was added to mysql_lock_tables().
sql/sql_parse.cc:
  multi_delete_set_locks_and_link_aux_tables():
    Adjust type of metadata lock to be requested after changing
    type of thr_lock.c lock for table list element from one
    which was set in parser to TL_WRITE.
    This removes discrepancy between types of these locks which
    allowed deadlocks to creep in.
sql/sql_show.cc:
  Use newly introduced MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL
  flag in order to acquire SH metadata locks when opening tables
  in I_S implementation.
sql/sql_update.cc:
  Added comment explaining why in multi-update after deciding
  that we need weaker thr_lock.c lock on a table we don't
  downgrade metadata lock on it.
sql/sql_view.cc:
  When merging view into main statement adjust type of metadata
  lock to be requested after changing type of thr_lock.c lock
  for table. This removes discrepancy between types of these
  locks which allowed deadlocks to creep in.
2010-02-08 23:19:55 +03:00
Jon Olav Hauglid
82f4494125 Bug #50907 Assertion `hash_tables->table->next == __null' on
HANDLER OPEN

The problem was a too restrictive assert in the code for 
HANDLER ... OPEN and HANDLER ... READ that checked table->next
to verify that we didn't open views or merge tables.

This pointer is also used to link temporary tables together
(see thd->temporary_tables). In this case TABLE::next can be
set even if we're trying to open a single table.

This patch adjust the two asserts to also check for the presence
of temporary tables.

Test case added to handler_myisam.test.
2010-02-05 15:52:17 +01:00
Konstantin Osipov
665100b69d Merge next-mr -> next-4284. 2010-02-02 02:22:16 +03:00
Dmitry Lenev
eba5d30e67 Implement new type-of-operation-aware metadata locks.
Add a wait-for graph based deadlock detector to the
MDL subsystem.

Fixes bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock" and
bug #37346 "innodb does not detect deadlock between update and
alter table".

The first bug manifested itself as an unwarranted abort of a
transaction with ER_LOCK_DEADLOCK error by a concurrent ALTER
statement, when this transaction tried to repeat use of a
table, which it has already used in a similar fashion before
ALTER started.

The second bug showed up as a deadlock between table-level
locks and InnoDB row locks, which was "detected" only after
innodb_lock_wait_timeout timeout.

A transaction would start using the table and modify a few
rows.
Then ALTER TABLE would come in, and start copying rows
into a temporary table. Eventually it would stumble on
the modified records and get blocked on a row lock.
The first transaction would try to do more updates, and get
blocked on thr_lock.c lock.
This situation of circular wait would only get resolved
by a timeout.

Both these bugs stemmed from inadequate solutions to the
problem of deadlocks occurring between different
locking subsystems.

In the first case we tried to avoid deadlocks between metadata
locking and table-level locking subsystems, when upgrading shared
metadata lock to exclusive one.
Transactions holding the shared lock on the table and waiting for
some table-level lock used to be aborted too aggressively.

We also allowed ALTER TABLE to start in presence of transactions
that modify the subject table. ALTER TABLE acquires
TL_WRITE_ALLOW_READ lock at start, and that block all writes
against the table (naturally, we don't want any writes to be lost
when switching the old and the new table). TL_WRITE_ALLOW_READ
lock, in turn, would block the started transaction on thr_lock.c
lock, should they do more updates. This, again, lead to the need
to abort such transactions.

The second bug occurred simply because we didn't have any
mechanism to detect deadlocks between the table-level locks
in thr_lock.c and row-level locks in InnoDB, other than
innodb_lock_wait_timeout.

This patch solves both these problems by moving lock conflicts
which are causing these deadlocks into the metadata locking
subsystem, thus making it possible to avoid or detect such
deadlocks inside MDL.

To do this we introduce new type-of-operation-aware metadata
locks, which allow MDL subsystem to know not only the fact that
transaction has used or is going to use some object but also what
kind of operation it has carried out or going to carry out on the
object.

This, along with the addition of a special kind of upgradable
metadata lock, allows ALTER TABLE to wait until all
transactions which has updated the table to go away.
This solves the second issue.
Another special type of upgradable metadata lock is acquired
by LOCK TABLE WRITE. This second lock type allows to solve the
first issue, since abortion of table-level locks in event of
DDL under LOCK TABLES becomes also unnecessary.

Below follows the list of incompatible changes introduced by
this patch:

- From now on, ALTER TABLE and CREATE/DROP TRIGGER SQL (i.e. those
  statements that acquire TL_WRITE_ALLOW_READ lock)
  wait for all transactions which has *updated* the table to
  complete.

- From now on, LOCK TABLES ... WRITE, REPAIR/OPTIMIZE TABLE
  (i.e. all statements which acquire TL_WRITE table-level lock) wait
  for all transaction which *updated or read* from the table
  to complete.
  As a consequence, innodb_table_locks=0 option no longer applies
  to LOCK TABLES ... WRITE.

- DROP DATABASE, DROP TABLE, RENAME TABLE no longer abort
  statements or transactions which use tables being dropped or
  renamed, and instead wait for these transactions to complete.

- Since LOCK TABLES WRITE now takes a special metadata lock,
  not compatible with with reads or writes against the subject table
  and transaction-wide, thr_lock.c deadlock avoidance algorithm
  that used to ensure absence of deadlocks between LOCK TABLES
  WRITE and other statements is no longer sufficient, even for
  MyISAM. The wait-for graph based deadlock detector of MDL
  subsystem may sometimes be necessary and is involved. This may
  lead to ER_LOCK_DEADLOCK error produced for multi-statement
  transactions even if these only use MyISAM:

  session 1:         session 2:
  begin;

  update t1 ...      lock table t2 write, t1 write;
                     -- gets a lock on t2, blocks on t1

  update t2 ...
  (ER_LOCK_DEADLOCK)

- Finally,  support of LOW_PRIORITY option for LOCK TABLES ... WRITE
  was abandoned.
  LOCK TABLE ... LOW_PRIORITY WRITE from now on has the same
  priority as the usual LOCK TABLE ... WRITE.
  SELECT HIGH PRIORITY no longer trumps LOCK TABLE ... WRITE  in
  the wait queue.

- We do not take upgradable metadata locks on implicitly
  locked tables. So if one has, say, a view v1 that uses
  table t1, and issues:
  LOCK TABLE v1 WRITE;
  FLUSH TABLE t1; -- (or just 'FLUSH TABLES'),
  an error is produced.
  In order to be able to perform DDL on a table under LOCK TABLES,
  the table must be locked explicitly in the LOCK TABLES list.

mysql-test/include/handler.inc:
  Adjusted test case to trigger an execution path on which bug 41110
  "crash with handler command when used concurrently with alter
  table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data
  with alter table" were originally discovered. Left old test case
  which no longer triggers this execution path for the sake of
  coverage.
  Added test coverage for HANDLER SQL statements and type-aware
  metadata locks.
  Added a test for the global shared lock and HANDLER SQL.
  Updated tests to take into account that the old simple deadlock
  detection heuristics was replaced with a graph-based deadlock
  detector.
mysql-test/r/debug_sync.result:
  Updated results (see debug_sync.test).
mysql-test/r/handler_innodb.result:
  Updated results (see handler.inc test).
mysql-test/r/handler_myisam.result:
  Updated results (see handler.inc test).
mysql-test/r/innodb-lock.result:
  Updated results (see innodb-lock.test).
mysql-test/r/innodb_mysql_lock.result:
  Updated results (see innodb_mysql_lock.test).
mysql-test/r/lock.result:
  Updated results (see lock.test).
mysql-test/r/lock_multi.result:
  Updated results (see lock_multi.test).
mysql-test/r/lock_sync.result:
  Updated results (see lock_sync.test).
mysql-test/r/mdl_sync.result:
  Updated results (see mdl_sync.test).
mysql-test/r/sp-threads.result:
  SHOW PROCESSLIST output has changed due to the fact that waiting
  for LOCK TABLES WRITE now happens within metadata locking
  subsystem.
mysql-test/r/truncate_coverage.result:
  Updated results (see truncate_coverage.test).
mysql-test/suite/funcs_1/datadict/processlist_val.inc:
  SELECT FROM I_S.PROCESSLIST output has changed due to fact that
  waiting for LOCK TABLES WRITE now happens within metadata locking
  subsystem.
mysql-test/suite/funcs_1/r/processlist_val_no_prot.result:
  SELECT FROM I_S.PROCESSLIST output has changed due to fact that
  waiting for LOCK TABLES WRITE now happens within metadata locking
  subsystem.
mysql-test/suite/rpl/t/rpl_sp.test:
  Updated to a new SHOW PROCESSLIST state name.
mysql-test/t/debug_sync.test:
  Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter
  no longer allows to trigger execution path involving waiting on
  thr_lock.c lock and therefore reaching debug sync-point covered
  by this test.
mysql-test/t/innodb-lock.test:
  Adjusted test case to the fact that innodb_table_locks=0 option is
  no longer supported, since LOCK TABLES WRITE handles all its
  conflicts within MDL subsystem.
mysql-test/t/innodb_mysql_lock.test:
  Added test for bug #37346 "innodb does not detect deadlock between
  update and alter table".
mysql-test/t/lock.test:
  Added test coverage which checks the fact that we no longer support
  DDL under LOCK TABLES on tables which were locked implicitly.
  Adjusted existing test cases accordingly.
mysql-test/t/lock_multi.test:
  Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary
  deadlock".  Adjusted other test cases to take into account the
  fact that waiting for LOCK TABLES ... WRITE now happens within MDL
  subsystem.
mysql-test/t/lock_sync.test:
  Since LOCK TABLES ... WRITE now takes SNRW metadata lock for
  tables locked explicitly we have to implicitly lock InnoDB tables
  (through view) to trigger the table-level lock conflict between
  TL_WRITE and TL_WRITE_ALLOW_WRITE.
mysql-test/t/mdl_sync.test:
  Added basic test coverage for type-of-operation-aware metadata
  locks. Also covered with tests some use cases involving HANDLER
  statements in which a deadlock could arise.
  Adjusted existing tests to take type-of-operation-aware MDL into
  account.
mysql-test/t/multi_update.test:
  Update to a new SHOW PROCESSLIST state name.
mysql-test/t/truncate_coverage.test:
  Adjusted test case after making LOCK TABLES WRITE to wait until
  transactions that use the table to be locked are completed.
  Updated to the changed name of DEBUG_SYNC point.
sql/handler.cc:
  Global read lock functionality has been
  moved into a class.
sql/lock.cc:
  Global read lock functionality has been
  moved into a class.
  Updated code to use the new MDL API.
sql/mdl.cc:
  Introduced new type-of-operation aware metadata locks.
  To do this:
  - Changed MDL_lock to use one list for waiting requests and one
    list for granted requests. For each list, added a bitmap
    that holds information what lock types a list contains.
    Added a helper class MDL_lock::List to manipulate with granted
    and waited lists while keeping the bitmaps in sync
    with list contents.
  - Changed lock-compatibility functions to use bitmaps that
    define compatibility.
  - Introduced a graph based deadlock detector inspired by
    waiting_threads.c from Maria implementation.
  - Now that we have a deadlock detector, and no longer have
    a global lock to protect individual lock objects, but rather
    use an rw lock per object, removed redundant code for upgrade,
    and the global read lock. Changed the MDL API to
    no longer require the caller to acquire the global
    intention exclusive lock by means of a separate method.
    Removed a few more methods that became redundant.
  - Removed deadlock detection heuristic, it has been made
    obsolete by the deadlock detector.
  - With operation-type-aware metadata locks, MDL subsystem has
    become aware of potential conflicts between DDL and open
    transactions. This made it possible to remove calls to
    mysql_abort_transactions_with_shared_lock() from acquisition
    paths for exclusive lock and lock upgrade. Now we can simply
    wait for these transactions to complete without fear of
    deadlock. Function mysql_lock_abort() has also become
    unnecessary for all conflicting cases except when a DDL
    conflicts with a connection that has an open HANDLER.
sql/mdl.h:
  Introduced new type-of-operation aware metadata locks.
  Introduced a graph based deadlock detector and supporting
  methods.
  Added comments.
  God rid of redundant API calls.
  Renamed m_lt_or_ha_sentinel to m_trans_sentinel,
  since now it guards the global read lock as well as
  LOCK TABLES and HANDLER locks.
sql/mysql_priv.h:
  Moved the global read lock functionality into a
  class.
  Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces
  open_tables() to take MDL_SHARED on tables instead of
  metadata locks specified in the parser. We use this to
  allow PREPARE run concurrently in presence of
  LOCK TABLES ... WRITE.
  Added signature for find_table_for_mdl_ugprade().
sql/set_var.cc:
  Global read lock functionality has been
  moved into a class.
sql/sp_head.cc:
  When creating TABLE_LIST elements for prelocking or
  system tables set the type of request for metadata
  lock according to the operation that will be performed
  on the table.
sql/sql_base.cc:
  - Updated code to use the new MDL API.
  - In order to avoid locks starvation we take upgradable
    locks all at once. As result implicitly locked tables no
    longer get an upgradable lock. Consequently DDL and FLUSH
    TABLES for such tables is prohibited.
    find_write_locked_table() was replaced by
    find_table_for_mdl_upgrade() function.
    open_table() was adjusted to return TABLE instance with
    upgradable ticket when necessary.
  - We no longer wait for all locks on OT_WAIT back off
    action -- only on the lock that caused the wait
    conflict. Moreover, now we distinguish cases when we
    have to wait due to conflict in MDL and old version
    of table in TDC.
  - Upate mysql_notify_threads_having_share_locks()
    to only abort thr_lock.c waits of threads that
    have open HANDLERs, since lock conflicts with only
    these threads now can lead to deadlocks not detectable
    by the MDL deadlock detector.
  - Remove mysql_abort_transactions_with_shared_locks()
    which is no longer needed.
sql/sql_class.cc:
  Global read lock functionality has been moved into a class.
  Re-arranged code in THD::cleanup() to simplify assert.
sql/sql_class.h:
  Introduced class to incapsulate global read lock
  functionality.
  Now sentinel in MDL subsystem guards the global read lock
  as well as LOCK TABLES and HANDLER locks. Adjusted code
  accordingly.
sql/sql_db.cc:
  Global read lock functionality has been moved into a class.
sql/sql_delete.cc:
  We no longer acquire upgradable metadata locks on tables
  which are locked by LOCK TABLES implicitly. As result
  TRUNCATE TABLE is no longer allowed for such tables.
  Updated code to use the new MDL API.
sql/sql_handler.cc:
  Inform MDL_context about presence of open HANDLERs.
  Since HANLDERs break MDL protocol by acquiring table-level
  lock while holding only S metadata lock on a table MDL
  subsystem should take special care about such contexts (Now
  this is the only case when mysql_lock_abort() is used).
sql/sql_parse.cc:
  Global read lock functionality has been moved into a class.
  Do not take upgradable metadata locks when opening tables
  for CREATE TABLE SELECT as it is not necessary and limits
  concurrency.
  When initializing TABLE_LIST objects before adding them
  to the table list set the type of request for metadata lock
  according to the operation that will be performed on the
  table.
  We no longer acquire upgradable metadata locks on tables
  which are locked by LOCK TABLES implicitly. As result FLUSH
  TABLES is no longer allowed for such tables.
sql/sql_prepare.cc:
  Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening
  tables during PREPARE. This allows PREPARE to run
  concurrently in presence of LOCK TABLES ... WRITE.
sql/sql_rename.cc:
  Global read lock functionality has been moved into a class.
sql/sql_show.cc:
  Updated code to use the new MDL API.
sql/sql_table.cc:
  Global read lock functionality has been moved into a class.
  We no longer acquire upgradable metadata locks on tables
  which are locked by LOCK TABLES implicitly. As result DROP
  TABLE is no longer allowed for such tables.
  Updated code to use the new MDL API.
sql/sql_trigger.cc:
  Global read lock functionality has been moved into a class.
  We no longer acquire upgradable metadata locks on tables
  which are locked by LOCK TABLES implicitly. As result
  CREATE/DROP TRIGGER is no longer allowed for such tables.
  Updated code to use the new MDL API.
sql/sql_view.cc:
  Global read lock functionality has been moved into a class.
  Fixed results of wrong merge that led to misuse of GLR API.
  CREATE VIEW statement is not a commit statement.
sql/table.cc:
  When resetting TABLE_LIST objects for PS or SP re-execution
  set the type of request for metadata lock according to the
  operation that will be performed on the table. Do the same
  in auxiliary function initializing metadata lock requests
  in a table list.
sql/table.h:
  When initializing TABLE_LIST objects set the type of request
  for metadata lock according to the operation that will be
  performed on the table.
sql/transaction.cc:
  Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
Konstantin Osipov
dfdbc84585 A prerequisite patch for the fix for Bug#46224
"HANDLER statements within a transaction might lead to deadlocks".
Introduce a notion of a sentinel to MDL_context. A sentinel
is a ticket that separates all tickets in the context into two
groups: before and after it. Currently we can have (and need) only
one designated sentinel -- it separates all locks taken by LOCK
TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK
and all other locks, which must be released at COMMIT or ROLLBACK.
The tricky part is maintaining the sentinel up to date when
someone release its corresponding ticket. This can happen, e.g.
if someone issues DROP TABLE under LOCK TABLES (generally,
see all calls to release_all_locks_for_name()).
MDL_context::release_ticket() is modified to take care of it.

******
A fix and a test case for Bug#46224 "HANDLER statements within a
transaction might lead to deadlocks".

An attempt to mix HANDLER SQL statements, which are transaction-
agnostic, an open multi-statement transaction,
and DDL against the involved tables (in a concurrent connection) 
could lead to a deadlock. The deadlock would occur when
HANDLER OPEN or HANDLER READ would have to wait on a conflicting
metadata lock. If the connection that issued HANDLER statement
also had other metadata locks (say, acquired in scope of a 
transaction), a classical deadlock situation of mutual wait
could occur.

Incompatible change: entering LOCK TABLES mode automatically
closes all open HANDLERs in the current connection.

Incompatible change: previously an attempt to wait on a lock
in a connection that has an open HANDLER statement could wait
indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK
is produced.

The idea of the fix is to merge thd->handler_mdl_context
with the main mdl_context of the connection, used for transactional
locks. This makes deadlock detection possible, since all waits
with locks are "visible" and available to analysis in a single
MDL context of the connection.

Since HANDLER locks and transactional locks have a different life
cycle -- HANDLERs are explicitly open and closed, and so
are HANDLER locks, explicitly acquired and released, whereas
transactional locks "accumulate" till the end of a transaction
and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT,
a concept of "sentinel" was introduced to MDL_context.
All locks, HANDLER and others, reside in the same linked list.
However, a selected element of the list separates locks with
different life cycle. HANDLER locks always reside at the
end of the list, after the sentinel. Transactional locks are
prepended to the beginning of the list, before the sentinel.
Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only
release those locks that reside before the sentinel. HANDLER locks
must be released explicitly as part of HANDLER CLOSE statement,
or an implicit close. 
The same approach with sentinel
is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES
statement has never worked together, the implementation is
made simple and only maintains one sentinel, which is used either
for HANDLER locks, or for LOCK TABLES locks.


mysql-test/include/handler.inc:
  Add test coverage for Bug#46224 "HANDLER statements within a
  transaction might lead to deadlocks".
  Extended HANDLER coverage to cover a mix of HANDLER, transactions
  and DDL statements.
mysql-test/r/handler_innodb.result:
  Update results (Bug#46224).
mysql-test/r/handler_myisam.result:
  Update results (Bug#46224).
sql/lock.cc:
  Remove thd->some_tables_deleted, it's never used.
sql/log_event.cc:
  No need to check for thd->locked_tables_mode, 
  it's done inside release_transactional_locks().
sql/mdl.cc:
  Implement the concept of HANDLER and LOCK TABLES "sentinel".
  Implement a method to clone an acquired ticket.
  Do not return tickets beyond the sentinel when acquiring
  locks, create a copy.
  Remove methods to merge and backup MDL_context, they are now
  not used (Hurra!). This opens a path to a proper constructor
  and destructor of class MDL_context (to be done in a separate
  patch).
  Modify find_ticket() to provide information about where
  the ticket position is with regard to the sentinel.
sql/mdl.h:
  Add declarations necessary for the implementation of the concept
  of "sentinel", a dedicated ticket separating transactional and
  non-transactional locks.
sql/mysql_priv.h:
  Add mark_tmp_table_for_reuse() declaration, 
  a function to "close" a single session (temporary) table.
sql/sql_base.cc:
  Remove thd->some_tables_deleted.
  Modify deadlock-prevention asserts and deadlock detection
  heuristics to take into account that from now on HANDLER locks
  reside in the same locking context.
  Add broadcast_refresh() to mysql_notify_thread_having_shared_lock():
  this is necessary for the case when a thread having a shared lock
  is asleep in tdc_wait_for_old_versions(). This situation is only
  possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths
  that lead to tdc_wait_for_old_versions() always have an
  empty MDL_context). Previously the server would simply deadlock
  in this situation.
sql/sql_class.cc:
  Remove now unused member "THD::some_tables_deleted". 
  Move mysql_ha_cleanup() a few lines above in THD::cleanup() 
  to make sure that all handlers are closed when it's time to 
  destroy the MDL_context of this connection.
  Remove handler_mdl_context and handler_tables.
sql/sql_class.h:
  Remove THD::handler_tables, THD::handler_mdl_context,
  THD::some_tables_deleted.
sql/sql_handler.cc:
  Remove thd->handler_tables.
  Remove thd->handler_mdl_context.
  Rewrite mysql_ha_open() to have no special provision for MERGE
  tables, now that we don't have to manipulate with thd->handler_tables
  it's easy to do.
  Remove dead code.
  Fix a bug in mysql_ha_flush() when we would always flush
  a temporary HANDLER when mysql_ha_flush() is called (actually
  mysql_ha_flush() never needs to flush temporary tables).
sql/sql_insert.cc:
  Update a comment, no more thd->some_tables_deleted.
sql/sql_parse.cc:
  Implement an incompatible change: entering LOCK TABLES closes
  active HANDLERs, if any.
  Now that we have a sentinel, we don't need to check
  for thd->locked_tables_mode when releasing metadata locks in
  COMMIT/ROLLBACK.
sql/sql_plist.h:
  Add new (now necessary) methods to the list class.
sql/sql_prepare.cc:
  Make sure we don't release HANDLER locks when rollback to a
  savepoint, set to not keep locks taken at PREPARE.
sql/sql_servers.cc:
  Update to a new signature of MDL_context::release_all_locks().
sql/sql_table.cc:
  Remove thd->some_tables_deleted.
sql/transaction.cc:
  Add comments. 
  Make sure rollback to (MDL) savepoint works under LOCK TABLES and
  with HANDLER tables.
2009-12-22 19:09:15 +03:00
Marc Alff
0531f85e16 Merge cleanup 2009-12-11 12:45:44 -07:00
Jon Olav Hauglid
fb6b5ee462 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
Konstantin Osipov
f129367288 Merge with next-4284. 2009-12-10 11:41:03 +03:00
Konstantin Osipov
f26f632b44 Backport of:
------------------------------------------------------------
revno: 2617.68.25
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-next-bg-pre2-2
timestamp: Wed 2009-09-16 18:26:50 +0400
message:
  Follow-up for one of pre-requisite patches for fixing bug #30977
  "Concurrent statement using stored function and DROP FUNCTION
  breaks SBR".

  Made enum_mdl_namespace enum part of MDL_key class and removed MDL_
  prefix from the names of enum members. In order to do the latter
  changed name of PROCEDURE symbol to PROCEDURE_SYM (otherwise macro
  which was automatically generated for this symbol conflicted with
  MDL_key::PROCEDURE enum member).
2009-12-10 11:21:38 +03:00
Marc Alff
c082955f06 WL#2360 Performance schema
Part III: mysys instrumentation
2009-12-09 20:19:51 -07:00
unknown
832ad46641 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.

mysql-test/r/merge.result:
  The result of the test.
mysql-test/t/merge.test:
  Added a test based on the bug report, as well as a test of the more general
  scenario.
sql/sql_handler.cc:
  Added code to release all the locks.
2009-12-09 14:41:56 +01:00
Konstantin Osipov
351b912e85 Backport of:
----------------------------------------------------------
revno: 2617.69.25
committer: Konstantin Osipov <kostja@sun.com>
branch nick: 5.4-42546
timestamp: Fri 2009-08-14 23:52:00 +0400
message:
  A cleanup in open_tables() and lock_tables():
  change return type of these functions to bool from int,
  to follow convention in the rest of the code.
(Part of WL#4284 review fixes).

sql/mysql_priv.h:
  Change return type of open_talbes() and lock_tables() from
  int to bool.
sql/sql_base.cc:
  Change return type of open_tables() and lock_tables() from int to bool.
sql/sql_handler.cc:
  Use bool now that open_tables() returns bool.
2009-12-09 12:04:55 +03:00
Jon Olav Hauglid
546e16ebd8 Backport of revno: 2617.69.40
A pre-requisite patch for Bug#30977 "Concurrent statement using 
stored function and DROP FUNCTION breaks SBR".

This patch changes the MDL API by introducing a namespace for
lock keys: MDL_TABLE for tables and views and MDL_PROCEDURE
for stored procedures and functions. The latter is needed for
the fix for Bug#30977.
2009-12-09 09:51:20 +01:00
Jon Olav Hauglid
19ff2445b1 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
ce5c87a3d3 Backport of:
----------------------------------------------------------
revno: 2617.69.20
committer: Konstantin Osipov <kostja@sun.com>
branch nick: 5.4-4284-1-assert
timestamp: Thu 2009-08-13 18:29:55 +0400
message:
  WL#4284 "Transactional DDL locking"
  A review fix.
  Since WL#4284 implementation separated MDL_request and MDL_ticket,
  MDL_request becamse a utility object necessary only to get a ticket.
  Store it by-value in TABLE_LIST with the intent to merge
  MDL_request::key with table_list->table_name and table_list->db
  in future.
  Change the MDL subsystem to not require MDL_requests to
  stay around till close_thread_tables().
  Remove the list of requests from the MDL context.
  Requests for shared metadata locks acquired in open_tables()
  are only used as a list in recover_from_failed_open_table_attempt(),
  which calls mdl_context.wait_for_locks() for this list.
  To keep such list for recover_from_failed_open_table_attempt(),
  introduce a context class (Open_table_context), that collects
  all requests.
  A lot of minor cleanups and simplications that became possible
  with this change.


sql/event_db_repository.cc:
  Remove alloc_mdl_requests(). Now MDL_request instance is a member
  of TABLE_LIST, and init_one_table() initializes it.
sql/ha_ndbcluster_binlog.cc:
  Remove now unnecessary declaration and initialization
  of binlog_mdl_request.
sql/lock.cc:
  No need to allocate MDL requests in lock_table_names() now.
sql/log.cc:
  Use init_one_table() method, remove alloc_mdl_requests(),
  which is now unnecessary.
sql/log_event.cc:
  No need to allocate mdl_request separately now.
  Use init_one_table() method.
sql/log_event_old.cc:
  Update to the new signature of close_tables_for_reopen().
sql/mdl.cc:
  Update try_acquire_exclusive_lock() to be more easy to use.
  Function lock_table_name_if_not_cached() has been removed.
  Make acquire_shared_lock() signature consistent with
  try_acquire_exclusive_lock() signature.
  Remove methods that are no longer used.
  Update comments.
sql/mdl.h:
  Implement an assignment operator that doesn't
  copy MDL_key (MDL_key::operator= is private and
  should remain private).
  This is a hack to work-around assignment of TABLE_LIST
  by value in several places. Such assignments violate
  encapsulation, since only perform a shallow copy.
  In most cases these assignments are a hack on their own.
sql/mysql_priv.h:
  Update signatures of close_thread_tables() and close_tables_for_reopen().
sql/sp.cc:
  Allocate TABLE_LIST in thd->mem_root.
  Use init_one_table().
sql/sp_head.cc:
  Use init_one_table().
  Remove thd->locked_tables_root, it's no longer needed.
sql/sql_acl.cc:
  Use init_mdl_requests() and init_one_table().
sql/sql_base.cc:
  Update to new signatures of try_acquire_shared_lock() and
  try_acquire_exclusive_lock().
  Remove lock_table_name_if_not_cached().
  Fix a bug in open_ltable() that would not return ER_LOCK_DEADLOCK
  in case of a failed lock_tables() and a multi-statement
  transaction.
  Fix a bug in open_and_lock_tables_derived() that would
  not return ER_LOCK_DEADLOCK in case of a multi-statement
  transaction and a failure of lock_tables().
  Move assignment of enum_open_table_action to a method of Open_table_context, a new class that maintains information
  for backoff actions.
  Minor rearrangements of the code.
  Remove alloc_mdl_requests() in functions that work with system
  tables: instead the patch ensures that callers always initialize
  TABLE_LIST argument.
sql/sql_class.cc:
  THD::locked_tables_root is no more.
sql/sql_class.h:
  THD::locked_tables_root is no more.
  Add a declaration for Open_table_context class.
sql/sql_delete.cc:
  Update to use the simplified MDL API.
sql/sql_handler.cc:
  TABLE_LIST::mdl_request is stored by-value now.
  Ensure that mdl_request.ticket is NULL for every request
  that is passed into MDL, to satisfy MDL asserts.
  @ sql/sql_help.cc
  Function open_system_tables_for_read() no longer initializes
  mdl_requests.
  Move TABLE_LIST::mdl_request initialization closer to
  TABLE_LIST initialization.
sql/sql_help.cc:
  Function open_system_tables_for_read() no longer initializes
  mdl_requests.
  Move TABLE_LIST::mdl_request initialization closer to
  TABLE_LIST initialization.
sql/sql_insert.cc:
  Remove assignment by-value of TABLE_LIST in
  TABLEOP_HOOKS. We can't carry over a granted
  MDL ticket from one table list to another.
sql/sql_parse.cc:
  Change alloc_mdl_requests() -> init_mdl_requests().
  @todo We can remove init_mdl_requests() altogether
  in some places: all places that call add_table_to_list()
  already have mdl requests initialized.
sql/sql_plugin.cc:
  Use init_one_table().
  THD::locked_tables_root is no more.
sql/sql_servers.cc:
  Use init_one_table().
sql/sql_show.cc:
  Update acquire_high_priority_shared_lock() to use
  TABLE_LIST::mdl_request rather than allocate an own.
  Fix get_trigger_table_impl() to use init_one_table(),
  check for out of memory, follow the coding style.
sql/sql_table.cc:
  Update to work with TABLE_LIST::mdl_request by-value.
  Remove lock_table_name_if_not_cached().
  The code that used to delegate to it is quite simple and
  concise without it now.
sql/sql_udf.cc:
  Use init_one_table().
sql/sql_update.cc:
  Update to use the new signature of close_tables_for_reopen().
sql/table.cc:
  Move re-setting of mdl_requests for prepared statements
  and stored procedures from close_thread_tables() to
  reinit_stmt_before_use().
  Change alloc_mdl_requests() to init_mdl_requests().
  init_mdl_requests() is a hack that can't be deleted
  until we don't have a list-aware TABLE_LIST constructor.
  Hopefully its use will be minimal
sql/table.h:
  Change alloc_mdl_requests() to init_mdl_requests()
  TABLE_LIST::mdl_request is stored by value.
sql/tztime.cc:
  We no longer initialize mdl requests in open_system_tables_for*()
  functions. Move this initialization closer to initialization
  of the rest of TABLE_LIST members.
storage/myisammrg/ha_myisammrg.cc:
  Simplify mdl_request initialization.
2009-12-08 12:57:07 +03:00
Konstantin Osipov
a9013f8fba Backport of:
----------------------------------------------------------
revno: 2617.23.20
committer: Konstantin Osipov <kostja@sun.com>
branch nick: mysql-6.0-runtime
timestamp: Wed 2009-03-04 16:31:31 +0300
message:
  WL#4284 "Transactional DDL locking"
  Review comments: "Objectify" the MDL API.
  MDL_request and MDL_context still need manual construction and
  destruction, since they are used in environment that is averse
  to constructors/destructors.


sql/mdl.cc:
  Improve comments.
  Add asserts to backup()/restore_from_backup()/merge() methods.
  Fix an order bug in the error path of mdl_acquire_exclusive_locks():
  we used to first free a ticket object, and only then exclude
  it from the list of tickets.
2009-12-04 02:52:05 +03:00
Konstantin Osipov
f477e66ec5 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).


mysql-test/r/mdl_sync.result:
  Add test case result.
mysql-test/t/mdl_sync.test:
  Add test case for shared lock upgrade case.
sql/event_db_repository.cc:
  Rename mdl_alloc_lock to mdl_request_alloc.
sql/ha_ndbcluster_binlog.cc:
  Use new function names to initialize MDL lock requests.
sql/lock.cc:
  Rename MDL functions.
sql/log_event.cc:
  The MDL request now holds the table and database name data (MDL_KEY).
sql/mdl.cc:
  Move the MDL key to the MDL_LOCK structure in order to make the
  object suitable for allocation from a fixed-size allocator. This
  allows the simplification of the lists in the MDL_LOCK object,
  which now are just two, one for granted tickets and other for
  waiting (upgraders) tickets.
  
  Recursive requests for a shared lock on the same object can now
  be granted using the same lock ticket. This schema is only used
  for shared locks because that the only case that matters. This
  is used to avoid waste of resources in case a context (connection)
  already holds a shared lock on a object.
sql/mdl.h:
  Introduce a metadata lock object key which is used  to uniquely
  identify lock objects.
  
  Separate the structure used to represent pending lock requests
  from the structure used to represent granted metadata locks.
  
  Rename functions used to manipulate locks requests in order to
  have a more consistent function naming schema.
sql/sp_head.cc:
  Rename mdl_alloc_lock to mdl_request_alloc.
sql/sql_acl.cc:
  Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_base.cc:
  Various changes to accommodate that lock requests are separated
  from lock tickets (granted locks).
sql/sql_class.h:
  Last acquired lock before the savepoint was set.
sql/sql_delete.cc:
  Various changes to accommodate that lock requests are separated
  from lock tickets (granted locks).
sql/sql_handler.cc:
  Various changes to accommodate that lock requests are separated
  from lock tickets (granted locks).
sql/sql_insert.cc:
  Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_parse.cc:
  Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_plist.h:
  Typedef for iterator type.
sql/sql_plugin.cc:
  Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_servers.cc:
  Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_show.cc:
  Various changes to accommodate that lock requests are separated
  from lock tickets (granted locks).
sql/sql_table.cc:
  Various changes to accommodate that lock requests are separated
  from lock tickets (granted locks).
sql/sql_trigger.cc:
  Save reference to the lock ticket so it can be downgraded later.
sql/sql_udf.cc:
  Rename alloc_mdl_locks to alloc_mdl_requests.
sql/table.cc:
  Rename mdl_alloc_lock to mdl_request_alloc.
sql/table.h:
  Separate MDL lock requests from lock tickets (granted locks).
storage/myisammrg/ha_myisammrg.cc:
  Rename alloc_mdl_locks to alloc_mdl_requests.
2009-12-04 02:29:40 +03:00
Konstantin Osipov
124cda8a0a Backport of:
------------------------------------------------------------
revno: 2630.4.33
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w2
timestamp: Fri 2008-06-20 17:11:20 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After-review fixes in progress.

  Minimized dependency of mdl.cc on other modules (particularly
  made it independant of mysql_priv.h) in order to be able
  write unit tests for metadata locking subsystem.


sql/ha_ndbcluster_binlog.cc:
  Use newly introduced MAX_MDLKEY_LENGTH constant for allocating
  buffer for object key for metadata locking subsystem.
sql/log_event.cc:
  Use newly introduced MAX_MDLKEY_LENGTH constant for allocating
  buffer for object key for metadata locking subsystem.
sql/mdl.cc:
  Removed dependency on THD class (and thus on mysql_priv.h)
  by using direct access to members of st_my_thread_var instead
  of accessing THD::killed/enter_cond()/exit_cond().
sql/mdl.h:
  Added MAX_MDLKEY_LENGTH constant to be used for allocating
  buffers for key for metadata locking subsystem.
  Added declarations of server kernel functions used by metadata
  locking subsystem to mdl.h in order to decrease dependency of
  mdl.cc on other files.
sql/mysql_priv.h:
  Moved declaration of notify_thread_having_shared_lock() to the
  mdl.h (also renamed it to make clear in metadata locking code
  that it is a callback to SQL-layer).
sql/sql_base.cc:
  Renamed notify_thread_having_shared_lock() to make it clear
  in metadata locking subsystem code that it is a callback
  to SQL layer.
sql/sql_handler.cc:
  Use newly introduced MAX_MDLKEY_LENGTH constant for allocating
  buffer for object key for metadata locking subsystem.
sql/sql_show.cc:
  Use newly introduced MAX_MDLKEY_LENGTH constant for allocating
  buffer for object key for metadata locking subsystem.
2009-12-02 19:31:57 +03:00
Konstantin Osipov
e3b3907c4f Backport of:
------------------------------------------------------------
revno: 2630.4.32
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w2
timestamp: Thu 2008-06-19 16:39:58 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After-review fixes in progress.

  Ensure that metadata locking subsystem properly handles
  out-of-memory conditions. Clarified MDL interface by
  separating release of locks and removal of lock requests
  from the context.

sql/lock.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and 
  mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
sql/mdl.cc:
  Ensured that metadata locking subsystem properly handles
  out-of-memory conditions.
  Introduced new MDL_INITIALIZED state for metadata lock
  request which is used in all cases when lock is not acquired 
  and we have not associated request with object respesenting 
  lock.
  
  MDL_PENDING is now only used for requests for exclusive locks
  which are added to the MDL_LOCK::waiting_exclusive queue.
  mdl_release_lock(), mdl_acquire_exclusive_locks() and 
  mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  newly introduced mdl_remove_lock() to do this.
  Also renamed mdl_release_all_locks_for_name() to 
  emphasize that it also actually removes lock requests
  from the context.
  
  Finally mdl_try_acquire_exclusive_lock() is now returs
  information about encountered lock conflict in separate
  out parameter since its return value is used for distinguishing
  between error (e.g. due to OOM) and success.
sql/mdl.h:
  Introduced new MDL_INITIALIZED state for metadata lock
  request which is used in all cases when lock is not acquired 
  and we have not associated request with object respesenting 
  lock.
  
  MDL_PENDING is now only used for requests for exclusive locks
  which are added to the MDL_LOCK::waiting_exclusive queue.
  mdl_release_lock(), mdl_acquire_exclusive_locks() and 
  mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  newly introduced mdl_remove_lock() to do this.
  Also renamed mdl_release_all_locks_for_name() to 
  emphasize that it also actually removes lock requests
  from the context.
  
  Finally mdl_try_acquire_exclusive_lock() is now returs
  information about encountered lock conflict in separate
  out parameter since its return value is used for distinguishing
  between error (e.g. due to OOM) and success.
sql/sql_base.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
  Also adjusted open_table() to ensure that it 
  releases/removes metadata locks in case of error 
  after adding/acquiring them (unless keeping these
  lock requests is required for recovering action).
sql/sql_delete.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
sql/sql_handler.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
sql/sql_show.cc:
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
sql/sql_table.cc:
  Renamed mdl_release_all_locks_for_name() to emphasize
  that it also actually removes lock requests from the context.
  mdl_release_lock(), mdl_acquire_exclusive_locks() and mdl_try_acquire_exclusive_lock() are no longer responsible
  for removal of metadata lock requests from the context.
  One should explicitly call mdl_remove_all_locks() and
  mdl_remove_lock() to do this.
  Finally mdl_try_acquire_exclusive_lock() is now returs
  information about encountered lock conflict in separate
  out parameter since its return value is used for distinguishing
  between error (e.g. due to OOM) and success.
2009-12-02 19:15:40 +03:00
Konstantin Osipov
1480dafe2f Backport of:
------------------------------------------------------------
revno: 2630.8.3
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w4
timestamp: Thu 2008-06-05 10:48:36 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After-review fixes in progress.

  Adjust some comments that were using old terminology
  (name locks instead of exclusive metadata locks), brought
  some of them up-to-date with current situation in code.


sql/sql_base.cc:
  Adjusted comments to use proper terminology.
sql/sql_delete.cc:
  Adjusted comments to use proper terminology.
sql/sql_handler.cc:
  Adjusted comments to use proper terminology.
sql/sql_partition.cc:
  Adjusted comments to use proper terminology also fixed
  one comment to correspond to what really happens in code.
sql/sql_show.cc:
  Adjusted comments to use proper terminology.
sql/sql_table.cc:
  Adjusted comments to use proper terminology, brought
   one of them up-to-date with current situation.
sql/sql_trigger.cc:
  Adjusted comments to use proper terminology.
sql/table.h:
  Removed two unused members of TABLE_SHARE struct.
2009-12-01 16:51:50 +03:00
Konstantin Osipov
e23046d1bc Backport of:
------------------------------------------------------------
revno: 2630.4.17
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w2
timestamp: Thu 2008-05-29 16:52:56 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After review fixes in progress.

  "The great correction of names".

  Renamed MDL_LOCK and MDL_LOCK_DATA classes to make usage of
  these names in metadata locking subsystem consistent with
  other parts of server (i.e. thr_lock.cc). Now we MDL_LOCK_DATA
  corresponds to request for a lock and MDL_LOCK to the lock
  itself. Adjusted code in MDL subsystem and other places
  using these classes accordingly.
  Did similar thing for GLOBAL_MDL_LOCK_DATA class and also
  changed name of its members to correspond to names of
  MDL_LOCK_DATA members.
  Finally got rid of usage of one letter variables in MDL
  code since it makes code harder to search in (according
  to reviewer).
2009-12-01 01:33:22 +03:00
Konstantin Osipov
cf45b61a6a Backport of:
------------------------------------------------------------
revno: 2630.4.16
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w
timestamp: Thu 2008-05-29 09:45:02 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After review changes in progress.

  Tweaked some comments and did some renames to
  avoid ambiguites.


sql/mysql_priv.h:
  Removed name_lock_locked_table() function.
sql/sql_base.cc:
  Got rid of name_lock_locked_table() function after replacing
  the only call to it with its body.
  Simplified open_table() code by making "action" argument
  mandatory (i.e. one now should always pass non-0 pointer
  in this argument).
  Renamed TABLE_LIST::open_table_type to open_type to
  avoid confusing it with type of table.
  Adjusted comments according to review.
sql/sql_handler.cc:
  Added comment clarifying in which cases we can have TABLE::mdl_lock
  set to 0.
sql/sql_insert.cc:
  Now the 4th argument of open_table() is mandatory (it makes
  no sense to complicate open_table() code when we can simply
  pass dummy variable).
sql/sql_parse.cc:
  Renamed TABLE_LIST::open_table_type to open_type to
  avoid confusing it with type of table.
sql/sql_prepare.cc:
  Renamed TABLE_LIST::open_table_type to open_type to
  avoid confusing it with type of table.
sql/sql_table.cc:
  Now the 4th argument of open_table() is mandatory (it makes
  no sense to complicate open_table() code when we can simply
  pass dummy variable).
sql/sql_trigger.cc:
  Replaced the only call to name_lock_locked_table() function
  with its body.
sql/sql_view.cc:
  Renamed TABLE_LIST::open_table_type to open_type to
  avoid confusing it with type of table.
sql/table.h:
  Renamed TABLE_LIST::open_table_type to open_type (to
  avoid confusing it with type of table) and improved
  comments describing this member.
2009-12-01 01:13:06 +03:00
Konstantin Osipov
0dcead9f61 Backport of:
------------------------------------------------------------
revno: 2630.4.14
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w
timestamp: Wed 2008-05-28 12:16:03 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After review fixes in progress. Removed unused code and
  adjusted names of functions/methods to better reflect
  their current function.


sql/mysql_priv.h:
  Changed names of close_data_files_and_morph_locks() and
  close_handle_and_leave_table_as_lock() to better reflect
  their current function (locking is now responsibility
  of metadata locking subsystem).
sql/sql_base.cc:
  Changed names of close_data_files_and_morph_locks() and
  close_handle_and_leave_table_as_lock() to better reflect
  their current function (locking is now responsibility
  of metadata locking subsystem). Also adjusted comments
  describing these functions.
  Got rid of TABLE::open_placeholder since it is no longer
  used (its value is never read anywhere).
  TABLE::needs_reopen_or_name_lock() was renamed to needs_reopen()
  since we no longer use name-locks
sql/sql_handler.cc:
  TABLE::needs_reopen_or_name_lock() was renamed to needs_reopen()
  since we no longer use name-locks.
sql/sql_insert.cc:
  TABLE::needs_reopen_or_name_lock() was renamed to needs_reopen()
  since we no longer use name-locks
sql/sql_partition.cc:
  Changed name of close_data_files_and_morph_locks() to
  better reflect its current function (locking is now
  responsibility of metadata locking subsystem).
sql/sql_table.cc:
  Changed names of close_data_files_and_morph_locks() and
  close_handle_and_leave_table_as_lock() to better reflect
  their current function (locking is now responsibility
  of metadata locking subsystem).
  Got rid of TABLE::open_placeholder since it is no longer
  used.
sql/sql_trigger.cc:
  Changed name of close_data_files_and_morph_locks() to
  better reflect its current function (locking is now
  responsibility of metadata locking subsystem).
sql/table.h:
  Got rid of TABLE::open_placeholder which is no longer used
  altough its value was set in several places no code reads it).
  Removed unused TABLE::is_name_opened() method.
  Finally TABLE::needs_reopen_or_name_lock() was renamed to
  needs_reopen() since we no longer use name-locks.
2009-12-01 01:01:27 +03:00
Konstantin Osipov
aeebede195 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().
2009-11-30 22:03:37 +03:00
Konstantin Osipov
eff3780dd8 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.

.bzrignore:
  Add libmysqld/mdl.cc
libmysqld/CMakeLists.txt:
  Added mdl.cc to the list of files needed for building of libmysqld.
libmysqld/Makefile.am:
  Added files implementing new meta-data locking subsystem to the server.
mysql-test/include/handler.inc:
  Use separate connection for waiting while threads performing DDL
  operations conflicting with open HANDLER tables reach blocked
  state. This is required because now we check and close tables open
  by HANDLER statements in this connection conflicting with DDL in
  another each time open_tables() is called and thus select from I_S
  which is used for waiting will unblock DDL operations if issued
  from connection with open HANDLERs.
mysql-test/r/create.result:
  Adjusted test case after change in implementation of CREATE TABLE
  ... SELECT.  We no longer have special check in open_table() which
  catches the case when we select from the table created. Instead we
  rely on unique_table() call which happens after opening and
  locking all tables.
mysql-test/r/flush.result:
  FLUSH TABLES WITH READ LOCK can no longer happen under LOCK
  TABLES.  Updated test accordingly.
mysql-test/r/flush_table.result:
  Under LOCK TABLES we no longer allow to do FLUSH TABLES for tables
  locked for read. Updated test accordingly.
mysql-test/r/handler_innodb.result:
  Use separate connection for waiting while threads performing DDL
  operations conflicting with open HANDLER tables reach blocked
  state. This is required because now we check and close tables open
  by HANDLER statements in this connection conflicting with DDL in
  another each time open_tables() is called and thus select from I_S
  which is used for waiting will unblock DDL operations if issued
  from connection with open HANDLERs.
mysql-test/r/handler_myisam.result:
  Use separate connection for waiting while threads performing DDL
  operations conflicting with open HANDLER tables reach blocked
  state. This is required because now we check and close tables open
  by HANDLER statements in this connection conflicting with DDL in
  another each time open_tables() is called and thus select from I_S
  which is used for waiting will unblock DDL operations if issued
  from connection with open HANDLERs.
mysql-test/r/information_schema.result:
  Additional test for WL#3726 "DDL locking for all metadata
  objects".  Check that we use high-priority metadata lock requests
  when filling I_S tables.
  
  Rearrange tests to match 6.0 better (fewer merge conflicts).
mysql-test/r/kill.result:
  Added tests checking that DDL and DML statements waiting for
  metadata locks can be interrupted by KILL command.
mysql-test/r/lock.result:
  One no longer is allowed to do DROP VIEW under LOCK TABLES even if
  this view is locked by LOCK TABLES. The problem is that in such
  situation write locks on view are not mutually exclusive so
  upgrading metadata lock which is required for dropping of view
  will lead to deadlock.
mysql-test/r/partition_column_prune.result:
  Update results (same results in 6.0), WL#3726
mysql-test/r/partition_pruning.result:
  Update results (same results in 6.0), WL#3726
mysql-test/r/ps_ddl.result:
  We no longer invalidate prepared CREATE TABLE ... SELECT statement
  if target table changes. This is OK since it is not strictly
  necessary.
  
  
  The first change is wrong, is caused by FLUSH TABLE
  now flushing all unused tables. This is a regression that
  Dmitri fixed in 6.0 in a follow up patch.
mysql-test/r/sp.result:
  Under LOCK TABLES we no longer allow accessing views which were
  not explicitly locked. To access view we need to obtain metadata
  lock on it and doing this under LOCK TABLES may lead to deadlocks.
mysql-test/r/view.result:
  One no longer is allowed to do DROP VIEW under LOCK TABLES even if
  this view is locked by LOCK TABLES. The problem is that in such
  situation even "write locks" on view are not mutually exclusive so
  upgrading metadata lock which is required for dropping of view
  will lead to deadlock
mysql-test/r/view_grant.result:
  ALTER VIEW implementation was changed to open a view only after
  checking that user which does alter has appropriate privileges on
  it. This means that in case when user's privileges are
  insufficient for this we won't check that new view definer is the
  same as original one or user performing alter has SUPER privilege.
  Adjusted test case accordingly.
mysql-test/r/view_multi.result:
  Added test case for bug#25144 "replication / binlog with view
  breaks".
mysql-test/suite/rpl/t/disabled.def:
  Disable test for deprecated features (they don't work with new MDL).
mysql-test/t/create.test:
  Adjusted test case after change in implementation of CREATE TABLE
  ... SELECT.  We no longer have special check in open_table() which
  catches the case when we select from the table created. Instead we
  rely on unique_table() call which happens after opening and
  locking all tables.
mysql-test/t/disabled.def:
  Disable merge.test, subject of WL#4144
mysql-test/t/flush.test:
  
  FLUSH TABLES WITH READ LOCK can no longer happen under LOCK
  TABLES.  Updated test accordingly.
mysql-test/t/flush_table.test:
  Under LOCK TABLES we no longer allow to do FLUSH TABLES for tables
  locked for read. Updated test accordingly.
mysql-test/t/information_schema.test:
  Additional test for WL#3726 "DDL locking for all metadata
  objects".  Check that we use high-priority metadata lock requests
  when filling I_S tables.
  
  Rearrange the results for easier merges with 6.0.
mysql-test/t/kill.test:
  Added tests checking that DDL and DML statements waiting for
  metadata locks can be interrupted by KILL command.
mysql-test/t/lock.test:
  One no longer is allowed to do DROP VIEW under LOCK TABLES even if
  this view is locked by LOCK TABLES. The problem is that in such
  situation write locks on view are not mutually exclusive so
  upgrading metadata lock which is required for dropping of view
  will lead to deadlock.
mysql-test/t/lock_multi.test:
  Adjusted test case to the changes of status in various places
  caused by change in implementation FLUSH TABLES WITH READ LOCK,
  which is now takes global metadata lock before flushing tables and
  therefore waits on at these places.
mysql-test/t/ps_ddl.test:
  We no longer invalidate prepared CREATE TABLE ... SELECT statement
  if target table changes. This is OK since it is not strictly
  necessary.
  
  
  The first change is wrong, is caused by FLUSH TABLE
  now flushing all unused tables. This is a regression that
  Dmitri fixed in 6.0 in a follow up patch.
mysql-test/t/sp.test:
  Under LOCK TABLES we no longer allow accessing views which were
  not explicitly locked. To access view we need to obtain metadata
  lock on it and doing this under LOCK TABLES may lead to deadlocks.
mysql-test/t/trigger_notembedded.test:
  Adjusted test case to the changes of status in various places
  caused by change in implementation FLUSH TABLES WITH READ LOCK,
  which is now takes global metadata lock before flushing tables and
  therefore waits on at these places.
mysql-test/t/view.test:
  One no longer is allowed to do DROP VIEW under LOCK TABLES even if
  this view is locked by LOCK TABLES. The problem is that in such
  situation even "write locks" on view are not mutually exclusive so
  upgrading metadata lock which is required for dropping of view
  will lead to deadlock.
mysql-test/t/view_grant.test:
  ALTER VIEW implementation was changed to open a view only after
  checking that user which does alter has appropriate privileges on
  it. This means that in case when user's privileges are
  insufficient for this we won't check that new view definer is the
  same as original one or user performing alter has SUPER privilege.
  Adjusted test case accordingly.
mysql-test/t/view_multi.test:
  Added test case for bug#25144 "replication / binlog with view
  breaks".
sql/CMakeLists.txt:
  Added mdl.cc to the list of files needed for building of server.
sql/Makefile.am:
  Added files implementing new meta-data locking subsystem to the
  server.
sql/event_db_repository.cc:
  
  Allocate metadata lock requests objects (MDL_LOCK) on execution
  memory root in cases when TABLE_LIST objects is also allocated
  there or on stack.
sql/ha_ndbcluster.cc:
  Adjusted code to work nicely with new metadata locking subsystem.
  close_cached_tables() no longer has wait_for_placeholder argument.
  Instead of relying on this parameter and related behavior FLUSH
  TABLES WITH READ LOCK now takes global shared metadata lock.
sql/ha_ndbcluster_binlog.cc:
  Adjusted code to work with new metadata locking subsystem.
  close_cached_tables() no longer has wait_for_placeholder argument.
  Instead of relying on this parameter and related behavior FLUSH
  TABLES WITH READ LOCK now takes global shared metadata lock.
sql/handler.cc:
  update_frm_version():
    Directly update TABLE_SHARE::mysql_version member instead of
    going through all TABLE instances for this table (old code was a
    legacy from pre-table-definition-cache days).
sql/lock.cc:
  Use new metadata locking subsystem. Threw away most of functions
  related to name locking as now one is supposed to use metadata
  locking API instead.  In lock_global_read_lock() and
  unlock_global_read_lock() in order to avoid problems with global
  read lock sneaking in at the moment when we perform FLUSH TABLES
  or ALTER TABLE under LOCK TABLES and when tables being reopened
  are protected only by metadata locks we also have to take global
  shared meta data lock.
sql/log_event.cc:
  Adjusted code to work with new metadata locking subsystem.  For
  tables open by slave thread for applying RBR events allocate
  memory for lock request object in the same chunk of memory as
  TABLE_LIST objects for them. In order to ensure that we keep these
  objects around until tables are open always close tables before
  calling Relay_log_info::clear_tables_to_lock(). Use new auxiliary
  Relay_log_info::slave_close_thread_tables() method to enforce
  this.
sql/log_event_old.cc:
  Adjusted code to work with new metadata locking subsystem.  Since
  for tables open by slave thread for applying RBR events memory for
  lock request object is allocated in the same chunk of memory as
  TABLE_LIST objects for them we have to ensure that we keep these
  objects around until tables are open. To ensure this we always
  close tables before calling
  Relay_log_info::clear_tables_to_lock(). To enfore this we use
  new auxiliary Relay_log_info::slave_close_thread_tables()
  method.
sql/mdl.cc:
  Implemented new metadata locking subsystem and API described in
  WL3726 "DDL locking for all metadata objects".
sql/mdl.h:
  Implemented new metadata locking subsystem and API described in
  WL3726 "DDL locking for all metadata objects".
sql/mysql_priv.h:
  - close_thread_tables()/close_tables_for_reopen() now has one more
    argument which indicates that metadata locks should be released
    but not removed from the context in order to be used later in
    mdl_wait_for_locks() and tdc_wait_for_old_version().
  - close_cached_table() routine is no longer public.
  - Thread waiting in wait_while_table_is_used() can be now killed
    so this function returns boolean to make caller aware of such
    situation.
  - We no longer have  table cache as separate entity instead used
    and unused TABLE instances are linked to TABLE_SHARE objects in
    table definition cache.
  - Now third argument of open_table() is also used for requesting
    table repair or auto-discovery of table's new definition. So its
    type was changed from bool to enum.
  - Added tdc_open_view() function for opening view by getting its
    definition from disk (and table cache in future).
  - reopen_name_locked_table() no longer needs "link_in" argument as
    now we have exclusive metadata locks instead of dummy TABLE
    instances when this function is called.
  - find_locked_table() now takes head of list of TABLE instances
    instead of always scanning through THD::open_tables list. Also
    added find_write_locked_table() auxiliary.
  - reopen_tables(), close_cached_tables() no longer have
    mark_share_as_old and wait_for_placeholder arguments. Instead of
    relying on this parameters and related behavior FLUSH TABLES
    WITH READ LOCK now takes global shared metadata lock.
  - We no longer need drop_locked_tables() and
    abort_locked_tables().
  - mysql_ha_rm_tables() now always assume that LOCK_open is not
    acquired by caller.
  - Added notify_thread_having_shared_lock() callback invoked by
    metadata locking subsystem when acquiring an exclusive lock, for
    each thread that has a conflicting shared metadata lock.
  - Introduced expel_table_from_cache() as replacement for
    remove_table_from_cache() (the main difference is that this new
    function assumes that caller follows metadata locking protocol
    and never waits).
  - Threw away most of functions related to name locking. One should
    use new metadata locking subsystem and API instead.
sql/mysqld.cc:
  Got rid of call initializing/deinitializing table cache since now
  it is embedded into table definition cache. Added calls for
  initializing/ deinitializing metadata locking subsystem.
sql/rpl_rli.cc:
  Introduced auxiliary Relay_log_info::slave_close_thread_tables()
  method which is used for enforcing that we always close tables
  open for RBR before deallocating TABLE_LIST elements and MDL_LOCK
  objects for them.
sql/rpl_rli.h:
  Introduced auxiliary Relay_log_info::slave_close_thread_tables()
  method which is used for enforcing that we always close tables
  open for RBR before deallocating TABLE_LIST elements and MDL_LOCK
  objects for them.
sql/set_var.cc:
  close_cached_tables() no longer has wait_for_placeholder argument.
  Instead of relying on this parameter and related behavior FLUSH
  TABLES WITH READ LOCK now takes global shared metadata lock.
sql/sp_head.cc:
  For tables added to the statement's table list by prelocking
  algorithm we allocate these objects either on the same memory as
  corresponding table list elements or on THD::locked_tables_root
  (if we are building table list for LOCK TABLES).
sql/sql_acl.cc:
  Allocate metadata lock requests objects (MDL_LOCK) on execution
  memory root in cases when we use stack TABLE_LIST objects to open
  tables.  Got rid of redundant code by using unlock_locked_tables()
  function.
sql/sql_base.cc:
  Changed code to use new MDL subsystem. Got rid of separate table
  cache.  Now used and unused TABLE instances are linked to the
  TABLE_SHAREs in table definition cache.
  
  check_unused():
    Adjusted code to the fact that we no longer have separate table
    cache.  Removed dead code.
  table_def_free():
    Free TABLE instances referenced from TABLE_SHARE objects before
    destroying table definition cache.
  get_table_share():
    Added assert which ensures that noone will be able to access
    table (and its share) without acquiring some kind of metadata
    lock first.
  close_handle_and_leave_table_as_lock():
    Adjusted code to the fact that TABLE instances now are linked to
    list in TABLE_SHARE.
  list_open_tables():
    Changed this function to use table definition cache instead of
    table cache.
  free_cache_entry():
    Unlink freed TABLE elements from the list of all TABLE instances
    for the table in TABLE_SHARE.
  kill_delayed_thread_for_table():
    Added auxiliary for killing delayed insert threads for
    particular table.
  close_cached_tables():
    Got rid of wait_for_refresh argument as we now rely on global
    shared metadata lock to prevent FLUSH WITH READ LOCK sneaking in
    when we are reopening tables. Heavily reworked this function to
    use new MDL code and not to rely on separate table cache entity.
  close_open_tables():
    We no longer have separate table cache.
  close_thread_tables():
    Release metadata locks after closing all tables. Added skip_mdl
    argument which allows us not to remove metadata lock requests
    from the context in case when we are going to use this requests
    later in mdl_wait_for_locks() and tdc_wait_for_old_versions().
  close_thread_table()/close_table_for_reopen():
    Since we no longer have separate table cache and all TABLE
    instances are linked to TABLE_SHARE objects in table definition
    cache we have to link/unlink TABLE object to/from appropriate
    lists in the share.
  name_lock_locked_table():
   Moved redundant code to find_write_locked_table() function and
    adjusted code to the fact that wait_while_table_is_used() can
    now return with an error if our thread is killed.
  reopen_table_entry():
    We no longer need "link_in" argument as with MDL we no longer
    call this function with dummy TABLE object pre-allocated and
    added to the THD::open_tables. Also now we add newly-open TABLE
    instance to the list of share's used TABLE instances.
  table_cache_insert_placeholder():
    Got rid of name-locking legacy.
  lock_table_name_if_not_cached():
    Moved to sql_table.cc the only place where it is used. It was
    also reimplemented using new MDL API.
  open_table():
    - Reworked this function to use new MDL subsystem.
    - Changed code to deal with table definition cache directly
      instead of going through separate table cache.
    - Now third argument is also used for requesting table repair
      or auto-discovery of table's new definition. So its type was
      changed from bool to enum.
  find_locked_table()/find_write_locked_table():
    Accept head of list of TABLE objects as first argument and use
    this list instead of always searching in THD::open_tables list.
    Also added auxiliary for finding write-locked locked tables.
  reopen_table():
    Adjusted function to work with new MDL subsystem and to properly
    manuipulate with lists of used/unused TABLE instaces in
    TABLE_SHARE.
  reopen_tables():
    Removed mark_share_as_old parameter. Instead of relying on it
    and related behavior FLUSH TABLES WITH READ LOCK now takes
    global shared metadata lock. Changed code after removing
    separate table cache.
  drop_locked_tables()/abort_locked_tables():
    Got rid of functions which are no longer needed.
    unlock_locked_tables():
    Moved this function from sql_parse.cc and changed it to release
    memory which was used for allocating metadata lock requests for
    tables open and locked by LOCK TABLES.
  tdc_open_view():
    Intoduced function for opening a view by getting its definition
    from disk (and table cache in future).
  reopen_table_entry():
    Introduced function for opening table definitions while holding
    exclusive metatadata lock on it.
  open_unireg_entry():
   Got rid of this function. Most of its functionality is relocated
    to open_table() and open_table_fini() functions, and some of it
    to reopen_table_entry() and tdc_open_view(). Also code
    resposible for auto-repair and auto-discovery of tables was
    moved to separate function.
  open_table_entry_fini():
    Introduced function which contains common actions which finalize
    process of TABLE object creation.
  auto_repair_table():
    Moved code responsible for auto-repair of table being opened
    here.
  handle_failed_open_table_attempt()
    Moved code responsible for handling failing attempt to open
    table to one place (retry due to lock conflict/old version,
    auto-discovery and repair).
  open_tables():
    - Flush open HANDLER tables if they have old version of if there
      is conflicting metadata lock against them (before this moment
      we had this code in open_table()).
    - When we open view which should be processed via derived table
      on the second execution of prepared statement or stored
      routine we still should call open_table() for it in order to
      obtain metadata lock on it and prepare its security context.
    - In cases when we discover that some special handling of
      failure to open table is needed call
      handle_failed_open_table_attempt() which handles all such
      scenarios.
  open_ltable():
    Handling of various special scenarios of failure to open a table
    was moved to separate handle_failed_open_table_attempt()
    function.
  remove_db_from_cache():
    Removed this function as it is no longer used.
  notify_thread_having_shared_lock():
    Added callback which is invoked by MDL subsystem when acquiring
    an exclusive lock, for each thread that has a conflicting shared
    metadata lock.
  expel_table_from_cache():
    Introduced function for removing unused TABLE instances. Unlike
    remove_table_from_cache() it relies on caller following MDL
    protocol and having appropriate locks when calling it and thus
    does not do any waiting if table is still in use.
  tdc_wait_for_old_version():
    Added function which allows open_tables() to wait in cases when
    we discover that we should back-off due to presence of old
    version of table.
  abort_and_upgrade_lock():
    Use new MDL calls.
  mysql_wait_completed_table():
    Got rid of unused function.
  open_system_tables_for_read/for_update()/performance_schema_table():
    Allocate MDL_LOCK objects on execution memory root in cases when
    TABLE_LIST objects for corresponding tables is allocated on
    stack.
  close_performance_schema_table():
    Release metadata locks after closing tables.
  ******
  Use I_P_List for free/used tables list in the table share.
sql/sql_binlog.cc:
  Use Relay_log_info::slave_close_thread_tables() method to enforce
  that we always close tables open for RBR before deallocating
  TABLE_LIST elements and MDL_LOCK objects for them.
sql/sql_class.cc:
  Added meta-data locking contexts as part of Open_tables_state
  context.  Also introduced THD::locked_tables_root memory root
  which is to be used for allocating MDL_LOCK objects for tables in
  LOCK TABLES statement (end of lifetime for such objects is UNLOCK
  TABLES so we can't use statement or execution root for them).
sql/sql_class.h:
  Added meta-data locking contexts as part of Open_tables_state
  context.  Also introduced THD::locked_tables_root memory root
  which is to be used for allocating MDL_LOCK objects for tables in
  LOCK TABLES statement (end of lifetime for such objects is UNLOCK
  TABLES so we can't use statement or execution root for them).
  
  Note: handler_mdl_context and locked_tables_root and
  mdl_el_root will be removed by subsequent patches.
sql/sql_db.cc:
  mysql_rm_db() does not really need to call remove_db_from_cache()
  as it drops each table in the database using
  mysql_rm_table_part2(), which performs all necessary operations on
  table (definition) cache.
sql/sql_delete.cc:
  Use the new metadata locking API for TRUNCATE.
sql/sql_handler.cc:
  Changed HANDLER implementation to use new metadata locking
  subsystem.  Note that MDL_LOCK objects for HANDLER tables are
  allocated in the same chunk of heap memory as TABLE_LIST object
  for those tables.
sql/sql_insert.cc:
  mysql_insert():
    find_locked_table() now takes head of list of TABLE object as
    its argument instead of always scanning through THD::open_tables
    list.
  handle_delayed_insert():
    Allocate metadata lock request object for table open by delayed
    insert thread on execution memroot.  create_table_from_items():
    We no longer allocate dummy TABLE objects for tables being
    created if they don't exist. As consequence
    reopen_name_locked_table() no longer has link_in argument.
    open_table() now has one more argument which is not relevant for
    temporary tables.
sql/sql_parse.cc:
  - Moved unlock_locked_tables() routine to sql_base.cc and made
    available it in other files. Got rid of some redundant code by
    using this function.
  - Replaced boolean TABLE_LIST::create member with enum
    open_table_type member.
  - Use special memory root for allocating MDL_LOCK objects for
    tables open and locked by LOCK TABLES (these object should live
    till UNLOCK TABLES so we can't allocate them on statement nor
    execution memory root). Also properly set metadata lock
    upgradability attribure for those tables.
  - Under LOCK TABLES it is no longer allowed to flush tables which
    are not write-locked as this breaks metadata locking protocol
    and thus potentially might lead to deadlock.
  - Added auxiliary adjust_mdl_locks_upgradability() function.
sql/sql_partition.cc:
  Adjusted code to the fact that reopen_tables() no longer has
  "mark_share_as_old" argument. Got rid of comments which are no
  longer true.
sql/sql_plist.h:
  Added I_P_List template class for parametrized intrusive doubly
  linked lists and I_P_List_iterator for corresponding iterator.
  Unlike for I_List<> list elements of such list can participate in
  several lists. Unlike List<> such lists are doubly-linked and
  intrusive.
sql/sql_plugin.cc:
  Allocate metadata lock requests objects (MDL_LOCK) on execution
  memory root in cases when we use stack TABLE_LIST objects to open
  tables.
sql/sql_prepare.cc:
  Replaced boolean TABLE_LIST::create member with enum
  open_table_type member.  This allows easily handle situation in
  which instead of opening the table we want only to take exclusive
  metadata lock on it.
sql/sql_rename.cc:
  Use new metadata locking subsystem in implementation of RENAME
  TABLE.
sql/sql_servers.cc:
  Allocate metadata lock requests objects (MDL_LOCK) on execution
  memory root in cases when we use stack TABLE_LIST objects to open
  tables. Got rid of redundant code by using unlock_locked_tables()
  function.
sql/sql_show.cc:
  Acquire shared metadata lock when we are getting information for
  I_S table directly from TABLE_SHARE without doing full-blown table
  open.  We use high priority lock request in this situation in
  order to avoid deadlocks.
  Also allocate metadata lock requests objects (MDL_LOCK) on
  execution memory root in cases when TABLE_LIST objects are also
  allocated there
sql/sql_table.cc:
  mysql_rm_table():
    Removed comment which is no longer relevant.
  mysql_rm_table_part2():
    Now caller of mysql_ha_rm_tables() should not own LOCK_open.
    Adjusted code to use new metadata locking subsystem instead of
    name-locks.
  lock_table_name_if_not_cached():
    Moved this function from sql_base.cc to this file and
    reimplemented it using metadata locking API.
  mysql_create_table():
    Adjusted code to use new MDL API.
  wait_while_table_is_used():
    Changed function to use new MDL subsystem. Made thread waiting
    in it killable (this also led to introduction of return value so
    caller can distinguish successful executions from situations
    when waiting was aborted).
  close_cached_tables():
    Thread waiting in this function is killable now. As result it
    has return value for distinguishing between succes and failure.
    Got rid of redundant boradcast_refresh() call.
  prepare_for_repair():
    Use MDL subsystem instead of name-locks.
  mysql_admin_table():
    mysql_ha_rm_tables() now always assumes that caller doesn't own
    LOCK_open.
  mysql_repair_table():
    We should mark all elements of table list as requiring
    upgradable metadata locks.
  mysql_create_table_like():
    Use new MDL subsystem instead of name-locks.
  create_temporary_tables():
    We don't need to obtain metadata locks when creating temporary
    table.
  mysql_fast_or_online_alter_table():
    Thread waiting in wait_while_table_is_used() is now killable.
  mysql_alter_table():
    Adjusted code to work with new MDL subsystem and to the fact
    that threads waiting in what_while_table_is_used() and
    close_cached_table() are now killable.
sql/sql_test.cc:
  We no longer have separate table cache. TABLE instances are now
  associated with/linked to TABLE_SHARE objects in table definition
  cache.
sql/sql_trigger.cc:
  Adjusted code to work with new metadata locking subsystem.  Also
  reopen_tables() no longer has mark_share_as_old argument (Instead
  of relying on this parameter and related behavior FLUSH TABLES
  WITH READ LOCK now takes global shared metadata lock).
sql/sql_udf.cc:
  Allocate metadata lock requests objects (MDL_LOCK) on execution
  memory root in cases when we use stack TABLE_LIST objects to open
  tables.
sql/sql_update.cc:
  Adjusted code to work with new meta-data locking subsystem.
sql/sql_view.cc:
  Added proper meta-data locking to implementations of
  CREATE/ALTER/DROP VIEW statements. Now we obtain exclusive
  meta-data lock on a view before creating/ changing/dropping it.
  This ensures that all concurrent statements that use this view
  will finish before our statement will proceed and therefore we
  will get correct order of statements in the binary log.
  Also ensure that TABLE_LIST::mdl_upgradable attribute is properly
  propagated for underlying tables of view.
sql/table.cc:
  Added auxiliary alloc_mdl_locks() function for allocating metadata
  lock request objects for all elements of table list.
sql/table.h:
  TABLE_SHARE:
    Got rid of unused members. Introduced members for storing lists
    of used and unused TABLE objects for this share.
  TABLE:
    Added members for linking TABLE objects into per-share lists of
    used and unused TABLE instances. Added member for holding
    pointer to metadata lock for this table.
  TABLE_LIST:
    Replaced boolean TABLE_LIST::create member with enum
    open_table_type member.  This allows easily handle situation in
    which instead of opening the table we want only to take
    exclusive meta-data lock on it (we need this in order to handle
    ALTER VIEW and CREATE VIEW statements).
    Introduced new mdl_upgradable member for marking elements of
    table list for which we need to take upgradable shared metadata
    lock instead of plain shared metadata lock.  Added pointer for
    holding pointer to MDL_LOCK for the table.
  Added auxiliary alloc_mdl_locks() function for allocating metadata
  lock requests objects for all elements of table list.  Added
  auxiliary set_all_mdl_upgradable() function for marking all
  elements in table list as requiring upgradable metadata locks.
storage/myisammrg/ha_myisammrg.cc:
  Allocate MDL_LOCK objects for underlying tables of MERGE table.
  To be reworked once Ingo pushes his patch for WL4144.
2009-11-30 18:55:03 +03:00
Konstantin Osipov
9a9e8d2311 Backport of:
----------------------------------------------------------------------
ChangeSet@1.2571, 2008-04-08 12:30:06+02:00, vvaintroub@wva. +122 -0
  Bug#32082 : definition of VOID in my_global.h conflicts with Windows
  SDK headers
  
  VOID macro is now removed. Its usage is replaced with void cast.
  In some cases, where cast does not make much sense (pthread_*, printf, 
  hash_delete, my_seek), cast is ommited.


client/mysqladmin.cc:
  Bug#32082 : remove VOID macro
client/mysqldump.c:
  Bug#32082 : remove VOID macro
client/mysqlimport.c:
  Bug#32082 : remove VOID macro
client/mysqlslap.c:
  Bug#32082 : remove VOID macro
client/mysqltest.cc:
  Bug#32082 : remove VOID macro
client/sql_string.cc:
  Bug#32082 : remove VOID macro
extra/comp_err.c:
  Bug#32082 : remove VOID macro
extra/replace.c:
  Bug#32082 : remove VOID macro
include/my_alarm.h:
  Bug#32082 : remove VOID macro
include/my_global.h:
  Bug#32082 : remove VOID macro
libmysql/libmysql.c:
  Bug#32082 : remove VOID macro
mysys/errors.c:
  Bug#32082 : remove VOID macro
mysys/hash.c:
  Bug#32082 : remove VOID macro
mysys/mf_iocache2.c:
  Bug#32082 : remove VOID macro
mysys/mf_loadpath.c:
  Bug#32082 : remove VOID macro
mysys/mf_path.c:
  Bug#32082 : remove VOID macro
mysys/my_append.c:
  Bug#32082 : remove VOID macro
mysys/my_clock.c:
  Bug#32082 : remove VOID macro
mysys/my_copy.c:
  Bug#32082 : remove VOID macro
mysys/my_fstream.c:
  Bug#32082 : remove VOID macro
mysys/my_getwd.c:
  Bug#32082 : remove VOID macro
mysys/my_lib.c:
  Bug#32082 : remove VOID macro
mysys/my_lockmem.c:
  Bug#32082 : remove VOID macro
mysys/my_pthread.c:
  Bug#32082 : remove VOID macro
mysys/my_redel.c:
  Bug#32082 : remove VOID macro
mysys/stacktrace.c:
  Bug#32082 : remove VOID macro
mysys/thr_alarm.c:
  Bug#32082 : remove VOID macro
mysys/thr_lock.c:
  Bug#32082 : remove VOID macro
sql/derror.cc:
  Bug#32082 : remove VOID macro
sql/des_key_file.cc:
  Bug#32082 : remove VOID macro
sql/discover.cc:
  Bug#32082 : remove VOID macro
sql/field.cc:
  Bug#32082 : remove VOID macro
sql/filesort.cc:
  Bug#32082 : remove VOID macro
sql/ha_ndbcluster.cc:
  Bug#32082 : remove VOID macro
sql/ha_partition.cc:
  Bug#32082 : remove VOID macro
sql/handler.cc:
  Bug#32082 : remove VOID macro
sql/hostname.cc:
  Bug#32082 : remove VOID macro
sql/init.cc:
  Bug#32082 : remove VOID macro
sql/item.cc:
  Bug#32082 : remove VOID macro
sql/item_cmpfunc.cc:
  Bug#32082 : remove VOID macro
sql/item_strfunc.cc:
  Bug#32082 : remove VOID macro
sql/lock.cc:
  Bug#32082 : remove VOID macro
sql/log.cc:
  Bug#32082 : remove VOID macro
sql/log_event.cc:
  Bug#32082 : remove VOID macro
sql/mysqld.cc:
  Bug#32082 : remove VOID macro
sql/opt_range.h:
  Bug#32082 : remove VOID macro
sql/protocol.cc:
  Bug#32082 : remove VOID macro
sql/records.cc:
  Bug#32082 : remove VOID macro
sql/sp_head.cc:
  Bug#32082 : remove VOID macro
sql/sp_pcontext.cc:
  Bug#32082 : remove VOID macro
sql/sql_acl.cc:
  Bug#32082 : remove VOID macro
sql/sql_base.cc:
  Bug#32082 : remove VOID macro
sql/sql_cache.cc:
  Bug#32082 : remove VOID macro
sql/sql_connect.cc:
  Bug#32082 : remove VOID macro
sql/sql_db.cc:
  Bug#32082 : remove VOID macro
sql/sql_delete.cc:
  Bug#32082 : remove VOID macro
sql/sql_handler.cc:
  Bug#32082 : remove VOID macro
sql/sql_insert.cc:
  Bug#32082 : remove VOID macro
sql/sql_map.cc:
  Bug#32082 : remove VOID macro
sql/sql_parse.cc:
  Bug#32082 : remove VOID macro
sql/sql_select.cc:
  Bug#32082 : remove VOID macro
sql/sql_servers.cc:
  Bug#32082 : remove VOID macro
sql/sql_show.cc:
  Bug#32082 : remove VOID macro
sql/sql_string.cc:
  Bug#32082 : remove VOID macro
sql/sql_table.cc:
  Bug#32082 : remove VOID macro
sql/sql_test.cc:
  Bug#32082 : remove VOID macro
sql/sql_trigger.cc:
  Bug#32082 : remove VOID macro
sql/sql_update.cc:
  Bug#32082 : remove VOID macro
sql/sql_view.cc:
  Bug#32082 : remove VOID macro
sql/table.cc:
  Bug#32082 : remove VOID macro
sql/tztime.cc:
  Bug#32082 : remove VOID macro
sql/udf_example.c:
  Bug#32082 : remove VOID macro
sql/uniques.cc:
  Bug#32082 : remove VOID macro
sql/unireg.cc:
  Bug#32082 : remove VOID macro
storage/archive/ha_archive.cc:
  Bug#32082 : remove VOID macro
storage/blackhole/ha_blackhole.cc:
  Bug#32082 : remove VOID macro
storage/csv/ha_tina.cc:
  Bug#32082 : remove VOID macro
storage/csv/transparent_file.cc:
  Bug#32082 : remove VOID macro
storage/example/ha_example.cc:
  Bug#32082 : remove VOID macro
storage/federated/ha_federated.cc:
  Bug#32082 : remove VOID macro
storage/heap/hp_clear.c:
  Bug#32082 : remove VOID macro
storage/heap/hp_create.c:
  Bug#32082 : remove VOID macro
storage/heap/hp_test1.c:
  Bug#32082 : remove VOID macro
storage/heap/hp_test2.c:
  Bug#32082 : remove VOID macro
storage/innobase/handler/ha_innodb.cc:
  Bug#32082 : remove VOID macro
storage/myisam/ft_eval.c:
  Bug#32082 : remove VOID macro
storage/myisam/ha_myisam.cc:
  Bug#32082 : remove VOID macro
storage/myisam/mi_changed.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_check.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_close.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_create.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_dbug.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_delete.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_delete_all.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_dynrec.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_info.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_locking.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_log.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_open.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_packrec.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_panic.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_rsame.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_statrec.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_test1.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_test2.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_test3.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_update.c:
  Bug#32082 : remove VOID macro
storage/myisam/mi_write.c:
  Bug#32082 : remove VOID macro
storage/myisam/myisamchk.c:
  Bug#32082 : remove VOID macro
storage/myisam/myisamlog.c:
  Bug#32082 : remove VOID macro
storage/myisam/myisampack.c:
  Bug#32082 : remove VOID macro
storage/myisam/sort.c:
  Bug#32082 : remove VOID macro
storage/myisammrg/myrg_close.c:
  Bug#32082 : remove VOID macro
storage/myisammrg/myrg_create.c:
  Bug#32082 : remove VOID macro
storage/myisammrg/myrg_open.c:
  Bug#32082 : remove VOID macro
strings/str_test.c:
  Bug#32082 : remove VOID macro
tests/thread_test.c:
  Bug#32082 : remove VOID macro
2009-11-24 16:54:59 +03:00
Alexander Nozdrin
a708ba6524 Manual merge from mysql-next-mr. 2009-11-02 14:10:04 +03:00
Alexander Nozdrin
2dc132b209 Merge from mysql-next-mr. 2009-10-23 15:22:21 +04:00
Sergey Glukhov
96dbafaa8d Bug#35428 When selecting from INFORMATION_SCHEMA tables, incomplete metadata
backport to Betony
2009-10-23 14:19:54 +05:00
Konstantin Osipov
8ec23470f1 Backport of revno 2630.28.10, 2630.28.31, 2630.28.26, 2630.33.1,
2630.39.1, 2630.28.29, 2630.34.3, 2630.34.2, 2630.34.1, 2630.29.29,
2630.29.28, 2630.31.1, 2630.28.13, 2630.28.10, 2617.23.14 and
some other minor revisions.

This patch implements: 

WL#4264 "Backup: Stabilize Service Interface" -- all the
server prerequisites except si_objects.{h,cc} themselves (they can
be just copied over, when needed).

WL#4435: Support OUT-parameters in prepared statements.

(and all issues in the initial patches for these two
tasks, that were discovered in pushbuild and during testing).

Bug#39519: mysql_stmt_close() should flush all data
associated with the statement.

After execution of a prepared statement, send OUT parameters of the invoked
stored procedure, if any, to the client.

When using the binary protocol, send the parameters in an additional result
set over the wire.  When using the text protocol, assign out parameters to
the user variables from the CALL(@var1, @var2, ...) specification.

The following refactoring has been made:
  - Protocol::send_fields() was renamed to Protocol::send_result_set_metadata();
  - A new Protocol::send_result_set_row() was introduced to incapsulate
    common functionality for sending row data.
  - Signature of Protocol::prepare_for_send() was changed: this operation
    does not need a list of items, the number of items is fully sufficient.

The following backward incompatible changes have been made:
  - CLIENT_MULTI_RESULTS is now enabled by default in the client;
  - CLIENT_PS_MULTI_RESUTLS is now enabled by default in the client.

include/mysql.h:
  Add a new flag to MYSQL_METHODS::flush_use_result
  function pointer. This flag determines if all results
  should be flushed or only the first one:
      
  - if flush_all_results is TRUE, then cli_flush_use_result()
    will read/flush all pending results. I.e. it will read
    all packets while server status attribute indicates that
    there are more results. This is a new semantic, required
    to fix the bug.
              
  - if flush_all_results is FALSE, the old sematic
    is preserved -- i.e. cli_flush_use_result() reads data
    until first EOF-packet.
include/mysql.h.pp:
  Update the ABI with new calls (compatible changes).
include/mysql_com.h:
  Add CLIENT_PS_OUT_PARAMS -- a client capability indicating that the client supportsю
libmysql/libmysql.c:
  Add mysql_stmt_next_result() -- analogue of mysql_next_result() for binary protocol.
  Fix a minor bug in alloc_fields() -- not all members were copied over,
  and some only shallow-copied (catalog).
  Flush all results in mysql_stmt_close() (Bug#39519).
libmysqld/lib_sql.cc:
  Rename send_fields() -> send_result_set_metadata().
  Refactoring: change prepare_for_send() so that it accepts only 
  what it really needs -- a number of elements in the list.
mysql-test/r/ps.result:
  Update results: WL#4435.
mysql-test/t/ps.test:
  WL#4435: A test case for an SQL-part of the problem.
sql-common/client.c:
  Bug#39519.
  Implement new functionality in cli_flush_use_result():
  if flush_all_delete is TRUE, then it should read/flush
  all pending results.
sql/Makefile.am:
  Add a new header sql_prepare.h to the list
  of build headers.
sql/events.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/handler.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/mysql_priv.h:
  Move sql_prepare.cc-specific declarations to a new
  header - sql_prepare.h.
sql/procedure.h:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/protocol.cc:
  Move the logic responsible for sending of one result
  set row to the Protocol class. Define a template
  for end-of-statement action. 
  Refactoring: change prepare_for_send() so that it accepts 
  only what it really needs -- a number of elements in the list.
  Rename send_fields() to send_result_set_metadata().
sql/protocol.h:
  Update with new declarations (WL#4435).
  Rename send_fields() -> send_result_set_metadata().
  prepare_for_send() only needs the number of columns to send,
  and doesn't use the item list - update signature to require
  only what's needed.
  Add a new protocol type -- Protocol_local.
sql/repl_failsafe.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/slave.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/sql_acl.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/sql_base.cc:
  Include sql_prepare.h (for Reprepare_observer).
sql/sql_cache.cc:
  Extend the query cache flags block to be able
  to store a numeric id for the result format,
  not just a flag binary/non-binary.
sql/sql_class.cc:
  Update to use the rename of Protocol::send_fields()
  to Protocol::send_result_set_metadata().
  Use Protocol::send_one_result_set_row().
sql/sql_class.h:
  Move the declaration of Reprepare_observer to the 
  new header - sql_prepare.h.
  Update to the new signature of class Protocol::send_fields().
sql/sql_connect.cc:
  Use a protocol template method instead of
  raw NET layer API at the end of a statement.
sql/sql_cursor.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/sql_error.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/sql_handler.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
  Use new method Protocol::send_one_result_set_row().
sql/sql_help.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/sql_lex.cc:
  Initialize multi_statements variable.
  Add a handy constant for empty lex
  string.
sql/sql_lex.h:
  Add a separate member for a standalone
  parsing option - multi-statements support.
sql/sql_list.cc:
  sql_list.h is a standalone header now, 
  no need to include mysql_priv.h.
sql/sql_list.h:
  Make sql_list.h a stand-alone header.
sql/sql_parse.cc:
  Include sql_prepare.h for prepared
  statements- related declarations.
  Use a new Protocol template method to end
  each statement (send OK, EOF or ERROR to
  the client).
sql/sql_prepare.cc:
  Implement Execute Direct API (WL#4264), 
  currently unused. It will be used by the service
  interface (Backup).
  Use a new header - sql_prepare.h.
  Add support for OUT parameters in the 
  binary and text protocol (prepared statements 
  only).
sql/sql_prepare.h:
  Add a new header to contain (for now)
  all prepared statement- external
  related declarations.
sql/sql_profile.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/sql_repl.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/sql_select.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/sql_show.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/sql_string.h:
  Add a way to convert a String to LEX_STRING.
sql/sql_table.cc:
  Rename: Protocol::send_fields() -> 
  Protocol::send_result_set_metadata().
sql/sql_update.cc:
  Remove an extraneous my_error(). The error
  is already reported in update_non_unique_table_error().
sql/sql_yacc.yy:
  Support for multi-statements is an independent
  property of parsing, not derived from 
  the protocol type.
tests/mysql_client_test.c:
  Add tests for WL#4435 (binary protocol).
2009-10-22 00:02:06 +04:00
Konstantin Osipov
9b41c7532d Backport of:
----------------------------------------------------------
revno: 2617.22.5
committer: Konstantin Osipov <kostja@sun.com>
branch nick: mysql-6.0-runtime
timestamp: Tue 2009-01-27 05:08:48 +0300
message:
  Remove non-prefixed use of HASH.
  Always use my_hash_init(), my_hash_inited(), my_hash_search(),
  my_hash_element(), my_hash_delete(), my_hash_free() rather
  than non-prefixed counterparts (hash_init(), etc).
  Remove the backward-compatible defines.
2009-10-14 20:37:38 +04:00
Staale Smedseng
d6ca0cbb23 Merge from 5.0 2009-09-17 17:25:52 +02:00
Staale Smedseng
e5888b16af Bug #43414 Parenthesis (and other) warnings compiling MySQL
with gcc 4.3.2
      
This is the fifth patch cleaning up more GCC warnings about
variables used before initialized using the new macro
UNINIT_VAR().
2009-09-17 17:10:30 +02:00
Kristofer Pettersson
fae95a4933 Bug#45781 infinite hang/crash in "opening tables" after handler tries to open merge
table

The MERGE table storage engine does not support the HA_CAN_SQL_HANDLE feature
and any attempt to open the merge table will fail with ER_ILLEGAL_HA.

After an error occurred the tables that was opened must be closed again
or they will be left in an inconsistent state. However, the assumption
made in the code for closing and register handler tables was that only
one table will be opened, and this is not true for MERGE tables which
will cause multiple tables to open.

The next time a SELECT operation was issued on the merge table it
caused the system to freeze.

This patch fixes this issue by making sure that all tables which
are opened also are closed in the event of an error.


mysql-test/r/merge.result:
  Added test case for bug 45781
mysql-test/t/merge.test:
  Added test case for bug 45781
sql/sql_handler.cc:
  * mysql_ha_open() was never ment to open more than one table. If we encounter more tables, we should
    close all tables related to the current substatement and raise an exception.
2009-07-16 01:23:57 +02:00