Commit graph

251 commits

Author SHA1 Message Date
Jon Olav Hauglid
bf55d1fcf0 Merge from mysql-5.5-bugteam to mysql-5.5-runtime 2010-09-30 12:43:43 +02:00
Jon Olav Hauglid
a302953bf7 Bug #56595 RENAME TABLE causes assert on OS X
The problem was that RENAME TABLE caused an assert if the system variable
lower_case_table_names was 2 (default on Mac OS X) and the old table name
was given in upper case. This caused lowercase_table2.test to fail.

The assert checks that an exclusive metadata lock is held by the connection
trying to do RENAME TABLE - specificially during updates of table triggers.
The assert was triggered since the check is case sensitive and the lock
was held on the normalized (lower case) version of the table name.

This patch fixes the problem by making sure a normalized version of the
table name is used for the metadata lock check, while using a non-normalized
version of the table name for the rename of trigger files. The same is done
for ALTER TABLE ... RENAME.

Regression testing for the bug itself is already covered by
lowercase_table2.test. Additional coverage added to lowercase_fs_off.test.
2010-09-16 11:11:13 +02:00
Dmitry Shulga
029cc52c88 Auto-merge from mysql-5.1-bugteam. 2010-09-07 16:00:41 +07:00
Dmitry Shulga
d6f6db6f4c Fixed bug #55421 - Protocol::end_statement(): Assertion `0' on
multi-table UPDATE IGNORE.
The problem was that if there was an active SELECT statement
during trigger execution, an error risen during the execution
may cause a crash. The fix is to temporary reset LEX::current_select
before trigger execution and restore it afterwards. This way
errors risen during the trigger execution are processed as
if there was no active SELECT.

mysql-test/r/trigger_notembedded.result:
  added test case result for bug #55421.
mysql-test/t/trigger_notembedded.test:
  added test case for bug #55421.
sql/sql_trigger.cc:
  Reset thd->lex->current_select before start trigger execution
  and restore its original value after execution is finished.
  This is neccessery in order to set error status in 
  diagnostic_area in case of trigger execution failure.
2010-09-07 15:53:46 +07:00
Alexander Nozdrin
65c5e8dcbf Bug#27480 (Extend CREATE TEMPORARY TABLES privilege
to allow temp table operations) -- prerequisite patch #2.

Introduce a new form of find_temporary_table() function:
find_temporary_table() by a table key. It will be used
in further patches.

Replace find_temporary_table(table_list->db, table_list->name)
by more appropiate find_temporary_table(table_list) across
the codebase.
2010-08-31 13:52:56 +04:00
Konstantin Osipov
523066987d A fix for Bug#41158 "DROP TABLE holds LOCK_open during unlink()".
Remove acquisition of LOCK_open around file system operations,
since such operations are now protected by metadata locks.
Rework table discovery algorithm to not require LOCK_open.

No new tests added since all MDL locking operations are covered
in lock.test and mdl_sync.test, and as long as these tests
pass despite the increased concurrency, consistency must be
unaffected.

mysql-test/t/disabled.def:
  Disable NDB tests due to Bug#55799.
sql/datadict.cc:
  No longer necessary to protect ha_create_table() with
  LOCK_open. Serial execution is now ensured by metadata
  locks.
sql/ha_ndbcluster.cc:
  Do not manipulate with LOCK_open in cluster code.
sql/ha_ndbcluster_binlog.cc:
  Do not manipulate with LOCK_open in cluster code.
sql/ha_ndbcluster_binlog.h:
  Update function signature.
sql/handler.cc:
  Implement ha_check_if_table_exists().
  @todo: some engines provide ha_table_exists_in_engine()
  handlerton call, for those we perhaps shouldn't
  call ha_discover(), to be more efficient.
  Since currently it's only NDB, postpone till
  integration with NDB.
sql/handler.h:
  Declare ha_check_if_table_exists() function.
sql/mdl.cc:
  Remove an obsolete comment.
sql/sql_base.cc:
  Update to a new signature of close_cached_tables():
  from now on we always call it without LOCK_open.
  Update comments.
  Remove get_table_share_with_create(), we should
  not attempt to create a table under LOCK_open.
  Introduce get_table_share_with_discover() instead,
  which would request a back off action if the table
  exists in engine.
  Remove acquisition of LOCK_open for 
  data dictionary operations, such as check_if_table_exists().
  Do not use get_table_share_with_create/discover for views,
  where it's not needed.
  Make tdc_remove_table() optionally acquire LOCK_open
  to simplify usage of this function.
  Use the right mutex in the partitioning code when
  manipulating with thd->open_tables.
sql/sql_base.h:
  Update signatures of changes functions.
sql/sql_insert.cc:
  Do not wrap quick_rm_table() with LOCK_open acquisition, 
  this is unnecessary.
sql/sql_parse.cc:
  Update to the new calling convention of tdc_remove_table().
  Update to the new signature of close_cached_tables().
  Update comments.
sql/sql_rename.cc:
  Update to the new calling convention of tdc_remove_table().
  Remove acquisition of LOCK_open around filesystem
  operations.
sql/sql_show.cc:
  Remove get_trigger_table_impl().
  Do not acquire LOCK_open for a dirty read of the trigger
  file.
sql/sql_table.cc:
  Do not acquire LOCK_open for filesystem operations.
sql/sql_trigger.cc:
  Do not require LOCK_open for trigger file I/O.
sql/sql_truncate.cc:
  Update to the new signature of tdc_remove_table().
sql/sql_view.cc:
  Do not require LOCK_open for view I/O.
  Use tdc_remove_table() to expel view share.
  Update comments.
sql/sys_vars.cc:
  Update to the new signature of close_cached_tables().
2010-08-09 22:33:47 +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
Konstantin Osipov
cc6dabba37 Merge trunk-bugfixing -> trunk-runtime 2010-06-17 17:31:51 +04:00
Alexey Kopytov
f84b3f5c21 Manual merge from mysql-5.1-bugteam to mysql-trunk-merge.
conflicts:
   conflict      mysys/safemalloc.c
   conflict      sql/mysqld.cc
   conflict      sql/sp.cc
   conflict      sql/sql_lex.cc
   conflict      sql/sql_lex.h
   conflict      sql/sql_parse.cc
   conflict      sql/sql_prepare.cc
2010-06-11 17:48:24 +04:00
Alexey Kopytov
386929d3ae Manual merge from the bugfix tree.
conflicts:
   conflict      sql/sql_parse.cc
2010-06-11 16:52:06 +04:00
Alexey Kopytov
e5cf56ef80 Manual merge from the bugfix tree.
conflicts:
   conflict      sql/sql_parse.cc
2010-06-11 14:51:21 +04:00
Davi Arnaut
db2fe44c84 Merge of mysql-5.1-bugteam into mysql-trunk-merge. 2010-06-10 22:30:49 -03:00
Davi Arnaut
0f9ddfa9d8 Bug#42733: Type-punning warnings when compiling MySQL --
strict aliasing violations.

One somewhat major source of strict-aliasing violations and
related warnings is the SQL_LIST structure. For example,
consider its member function `link_in_list` which takes
a pointer to pointer of type T (any type) as a pointer to
pointer to unsigned char. Dereferencing this pointer, which
is done to reset the next field, violates strict-aliasing
rules and might cause problems for surrounding code that
uses the next field of the object being added to the list.

The solution is to use templates to parametrize the SQL_LIST
structure in order to deference the pointers with compatible
types. As a side bonus, it becomes possible to remove quite
a few casts related to acessing data members of SQL_LIST.

sql/handler.h:
  Use the appropriate template type argument.
sql/item.cc:
  Remove now-unnecessary cast.
sql/item_subselect.cc:
  Remove now-unnecessary casts.
sql/item_sum.cc:
  Use the appropriate template type argument.
  Remove now-unnecessary cast.
sql/mysql_priv.h:
  Move SQL_LIST structure to sql_list.h
  Use the appropriate template type argument.
sql/sp.cc:
  Remove now-unnecessary casts.
sql/sql_delete.cc:
  Use the appropriate template type argument.
  Remove now-unnecessary casts.
sql/sql_derived.cc:
  Remove now-unnecessary casts.
sql/sql_lex.cc:
  Remove now-unnecessary casts.
sql/sql_lex.h:
  SQL_LIST now takes a template type argument which must
  match the type of the elements of the list. Use forward
  declaration when the type is not available, it is used
  in pointers anyway.
sql/sql_list.h:
  Rename SQL_LIST to SQL_I_List. The template parameter is
  the type of object that is stored in the list.
sql/sql_olap.cc:
  Remove now-unnecessary casts.
sql/sql_parse.cc:
  Remove now-unnecessary casts.
sql/sql_prepare.cc:
  Remove now-unnecessary casts.
sql/sql_select.cc:
  Remove now-unnecessary casts.
sql/sql_show.cc:
  Remove now-unnecessary casts.
sql/sql_table.cc:
  Remove now-unnecessary casts.
sql/sql_trigger.cc:
  Remove now-unnecessary casts.
sql/sql_union.cc:
  Remove now-unnecessary casts.
sql/sql_update.cc:
  Remove now-unnecessary casts.
sql/sql_view.cc:
  Remove now-unnecessary casts.
sql/sql_yacc.yy:
  Remove now-unnecessary casts.
storage/myisammrg/ha_myisammrg.cc:
  Remove now-unnecessary casts.
2010-06-10 17:45:22 -03:00
Dmitry Lenev
ae1ae4bd63 Fix for bug #51263 "Deadlock between transactional
SELECT and ALTER TABLE ...  REBUILD PARTITION".

ALTER TABLE on InnoDB table (including partitioned tables)
acquired exclusive locks on rows of table being altered.
In cases when there was concurrent transaction which did
locking reads from this table this sometimes led to a
deadlock which was not detected by MDL subsystem nor by
InnoDB engine (and was reported only after exceeding
innodb_lock_wait_timeout).

This problem stemmed from the fact that ALTER TABLE acquired
TL_WRITE_ALLOW_READ lock on table being altered. This lock
was interpreted as a write lock and thus for table being
altered handler::external_lock() method was called with
F_WRLCK as an argument. As result InnoDB engine treated
ALTER TABLE as an operation which is going to change data
and acquired LOCK_X locks on rows being read from old
version of table.

In case when there was a transaction which already acquired
SR metadata lock on table and some LOCK_S locks on its rows
(e.g. by using it in subquery of DML statement) concurrent
ALTER TABLE was blocked at the moment when it tried to
acquire LOCK_X lock before reading one of these rows.
The transaction's attempt to acquire SW metadata lock on
table being altered led to deadlock, since it had to wait
for ALTER TABLE to release SNW lock. This deadlock was not
detected and got resolved only after timeout expiring
because waiting were happening in two different subsystems.

Similar deadlocks could have occured in other situations.
This patch tries to solve the problem by changing ALTER TABLE
implementation to use TL_READ_NO_INSERT lock instead of
TL_WRITE_ALLOW_READ. After this step handler::external_lock()
is called with F_RDLCK as an argument and InnoDB engine
correctly interprets ALTER TABLE as operation which only
reads data from original version of table. Thanks to this
ALTER TABLE acquires only LOCK_S locks on rows it reads.
This, in its turn, causes inter-subsystem deadlocks to go
away, as all potential lock conflicts and thus deadlocks will
be limited to metadata locking subsystem:

- When ALTER TABLE reads rows from table being altered it
  can't encounter any locks which conflict with LOCK_S row
  locks. There should be no concurrent transactions holding
  LOCK_X row locks. Such a transaction should have been
  acquired SW metadata lock on table first which would have
  conflicted with ALTER's SNW lock.
- Vice versa, when DML which runs concurrently with ALTER
  TABLE tries to lock row it should be requesting only LOCK_S
  lock which is compatible with locks acquired by ALTER,
  as otherwise such DML must own an SW metadata lock on table
  which would be incompatible with ALTER's SNW lock.

mysql-test/r/innodb_mysql_lock2.result:
  Added test for bug #51263 "Deadlock between transactional
  SELECT and ALTER TABLE ... REBUILD PARTITION".
mysql-test/suite/rpl_ndb/r/rpl_ndb_binlog_format_errors.result:
  Since CREATE TRIGGER no longer acquires write lock on table
  it is no longer interpreted as an operation which modifies
  table data and therefore no longer fails if invoked for
  SBR-only engine in ROW mode.
mysql-test/suite/rpl_ndb/t/rpl_ndb_binlog_format_errors.test:
  Since CREATE TRIGGER no longer acquires write lock on table
  it is no longer interpreted as an operation which modifies
  table data and therefore no longer fails if invoked for
  SBR-only engine in ROW mode.
mysql-test/t/innodb_mysql_lock2.test:
  Added test for bug #51263 "Deadlock between transactional
  SELECT and ALTER TABLE ... REBUILD PARTITION".
sql/ha_partition.cc:
  When ALTER TABLE creates a new partition to be filled from
  other partition lock it in F_WRLCK mode instead of using
  mode which was used for locking the whole table (it is
  F_RDLCK now).
sql/lock.cc:
  Replaced conditions which used TL_WRITE_ALLOW_READ
  lock type with equivalent conditions using
  TL_WRITE_ALLOW_WRITE. This should allow to get rid
  of TL_WRITE_ALLOW_READ lock type eventually.
sql/mdl.cc:
  Updated outdated comment to reflect current situation.
sql/sql_base.cc:
  Replaced conditions which used TL_WRITE_ALLOW_READ
  lock type with equivalent conditions using
  TL_WRITE_ALLOW_WRITE. This should allow to get rid
  of TL_WRITE_ALLOW_READ lock type eventually.
sql/sql_table.cc:
  mysql_admin_table():
    Use TL_WRITE_ALLOW_WRITE lock type instead of
    TL_WRITE_ALLOW_READ to determine that we need to acquire
    upgradable metadata lock. This should allow to completely
    get rid of TL_WRITE_ALLOW_READ in long term.
  mysql_recreate_table():
    ALTER TABLE now requires TL_READ_NO_INSERT thr_lock.c lock
    instead of TL_WRITE_ALLOW_READ.
sql/sql_trigger.cc:
  Changed CREATE/DROP TRIGGER implementation to use
  TL_READ_NO_INSERT lock instead of TL_WRITE_ALLOW_READ lock.
  The latter is no longer necessary since:
  a) We now can rely on metadata locks to achieve proper
     isolation between two DDL statements or DDL and DML
     statements.
  b) This statement does not change any data in table so there
     is no need to inform storage engine about it.
sql/sql_yacc.yy:
  Changed implementation of ALTER TABLE (and CREATE/DROP INDEX
  as a consequence) to use TL_READ_NO_INSERT lock instead of
  TL_WRITE_ALLOW_READ lock. This is possible since:
  a) We now can rely on metadata locks to achieve proper
     isolation between two DDL statements or DDL and DML
     statements.
  b) This statement only reads data in table being open.
     We write data only to the new version of table and
     then replace with it old version of table under
     X metadata lock.
  
  Thanks to this change InnoDB will no longer acquire LOCK_X
  locks on rows being read by ALTER TABLE (instead LOCK_S
  locks will be acquired) and thus cause of bug #51263
  "Deadlock between transactional SELECT and ALTER TABLE ...
  REBUILD PARTITION" is removed.
  
  Did the similar change for CREATE TRIGGER (see comments
  for sql_trigger.cc for details).
2010-05-26 16:18:08 +04:00
Dmitry Lenev
bee0f214fd Pre-requisite patch for bug #51263 "Deadlock between
transactional SELECT and ALTER TABLE ... REBUILD PARTITION".

The goal of this patch is to decouple type of metadata
lock acquired for table by open_tables() from type of
table-level lock to be acquired on it.

To achieve this we change approach to how we determine what
type of metadata lock should be acquired on table to be open.
Now instead of inferring it at open_tables() time from flags
and type of table-level lock we rely on that type of metadata
lock is properly set at parsing time and is not changed
further.

sql/ha_ndbcluster.cc:
  Now one needs to properly initialize table list element's
  MDL_request object before calling mysql_rm_table_part2().
sql/lock.cc:
  lock_table_names() no longer initializes table list elements'
  MDL_request objects. Now proper initialization of these
  requests is a responsibility of the caller.
sql/lock.h:
  Removed MYSQL_OPEN_TAKE_UPGRADABLE_MDL flag which became
  unnecessary. Thanks to the fact that we don't reset type of
  requests for metadata locks between re-executions we now can
  figure out that upgradable locks are requested by simply
  looking at their type which were set in the parser. As result
  this flag became redundant.
sql/mdl.h:
  Added version of new operator which simplifies allocation of
  MDL_request objects on a MEM_ROOT.
sql/sp_head.cc:
  Added comment explaining why it is OK to infer type of
  metadata lock to request from type of table-level lock
  for prelocking.
  Added enum_mdl_type argument to sp_add_to_query_tables()
  to simplify its usage in trigger implementation.
sql/sp_head.h:
  Added enum_mdl_type argument to sp_add_to_query_tables()
  to simplify its usage in trigger implementation.
sql/sql_base.cc:
  - open_table_get_mdl_lock():
    Preserve type of MDL_request for table list element which
    was set in the parser by creating MDL_request objects on
    memory root if MYSQL_OPEN_FORCE_SHARED_MDL or
    MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL flag were specified.
    Thanks to this and to the fact that we no longer reset
    type of requests for metadata locks between re-executions
    we no longer need to acquire exclusive metadata lock on
    table to be created in a special way. This lock is acquired
    by code handling acquiring of upgradable locks.
    Also changed signature/calling convention for this function
    to simplify its usage.
  - Accordingly special lock strategy for table list elements
    which was used for such locks became unnecessary and was
    removed. Other strategies were renamed.
  - Since we no longer have guarantee that MDL_request object
    which were not satisfied due to lock conflict belongs to
    table list element Open_table_context class and its methods
    were extended to remember pointer to MDL_request which has
    caused problem at request_backoff_action() time and use it
    in recover_from_failed_open(). Similar approach is used
    for cases when problem from which we need to recover is
    not related to MDL but to the table itself. In this case
    we store pointer to the element of table list.
  - Changed open_tables()/open_tables_check_upgradable_mdl()/
    open_tables_acquire_upgradable_mdl() not to rely on
    MYSQL_OPEN_TAKE_UPGRADABLE_MDL flag to understand when
    upgradable metadata locks should be acquired and not to
    infer type of MDL lock from type of table-level lock.
    Instead we assume that type of MDL to be acquired was set
    in the parser (we can do this as type of MDL_request is
    no longer reset between re-executions).
sql/sql_class.h:
  Since we no longer have guarantee that MDL_request object
  which were not satisfied due to lock conflict belongs to
  table list element Open_table_context class and its methods
  were extended to remember pointer to MDL_request which has
  caused problem at request_backoff_action() time and use it
  in recover_from_failed_open(). Similar approach is used
  for cases when problem from which we need to recover is
  not related to MDL but to the table itself. In this case
  we store pointer to the element of table list.
sql/sql_db.cc:
  Now one needs to properly initialize table list element's
  MDL_request object before calling mysql_rm_table_part2()
  or mysql_rename_tables().
sql/sql_lex.cc:
  st_select_lex/st_select_lex_node::add_table_to_list() method
  now has argument which allows specify type of metadata lock
  to be requested for table list element being added.
sql/sql_lex.h:
  - st_select_lex/st_select_lex_node::add_table_to_list()
    method now has argument which specifies type of metadata
    lock to be requested for table list element being added.
    This allows to explicitly set type of MDL lock to be
    acquired for a DDL statement in parser. It is also more
    future-proof than inferring type of MDL request from type
    of table-level lock.
  - Added Yacc_state::m_mdl_type member which specifies which
    type of metadata lock should be requested for tables to be
    added to table list by a grammar rule in cases when the same
    rule is used in several statements requiring different kinds
    of metadata locks.
sql/sql_parse.cc:
  - st_select_lex::add_table_to_list() method now has argument
    which specifies type of metadata lock to be requested for
    table list element being added. This allows to explicitly
    set type of MDL lock to be acquired for a DDL statement in
    parser. It is also more future-proof than inferring type of
    MDL request from type of table-level lock.
  - EXCLUSIVE_DOWNGRADABLE_MDL lock strategy has a new name -
    OTLS_DOWNGRADE_IF_EXISTS.
  - Adjusted LOCK TABLES implementation to the fact that we no
    longer infer type of metadata lock to be acquired from table
    level lock and that type of MDL request is set at parsing.
    And thus MYSQL_OPEN_TAKE_UPGRADABLE_MDL flag became
    unnecessary.
sql/sql_prepare.cc:
  TABLE_LIST's lock strategy SHARED_MDL was renamed to OTLS_NONE
  as now it means that metadata lock should not be changed during
  call to open_table() (if it has been already acquired) and is
  also used for exclusive metadata lock.
sql/sql_show.cc:
  st_select_lex::add_table_to_list() method now has argument
  which specifies type of metadata lock to be requested for
  table list element being added.
sql/sql_table.cc:
  - Adjusted mysql_admin_table()'s code to the fact that
    open_tables() no longer determines what kind of metadata
    lock should be obtained basing on type of table-level
    lock and flags. Instead type of metadata lock for table
    to be open should be set before calling open_tables().
  - Changed mysql_alter_table() code to the facts:
    a) that now it is responsibility of caller to properly
    initalize MDL_request in table list elements before calling
    lock_table_names()
    b) and that MYSQL_OPEN_TAKE_UPGRADABLE_MDL is no longer
    necessary since type of metadata lock to be obtained
    at open_tables() time is set during parsing.
  - Changed code of mysql_recreate_table() to properly set
    type of metadata and table-level lock to be obtained
    by mysql_alter_table() which it calls.
sql/sql_trigger.cc:
  Instead of relying on MYSQL_OPEN_TAKE_UPGRADABLE_MDL flag to
  force open_tables() to take an upgradable lock we now specify
  exact type of lock to be taken when constructing table list
  element for table to be open for CREATE/DROP TRIGGER.
sql/sql_view.cc:
  We no longer use TABLE_LIST::EXCLUSIVE_MDL strategy to force
  open_tables() to take an exclusive metadata lock on view to
  be created. Instead we rely on parser setting proper type of
  metadata lock to request and open_tables() acquiring it.
  This became possible thanks to the fact that we no longer
  reset type of MDL_request between statement re-executions.
sql/sql_yacc.yy:
  Instead of inferring type of MDL_request for table to be
  open from type of table-level lock and flags passed to
  open_tables() we now explicitly specify them at parsing.
  This became possible thanks to the fact that we no longer
  reset type of MDL_request between statement re-executions.
  In future this should allow to decouple type of metadata
  lock from type of table-level lock.
  The only exception to this approach is statements implemented
  through mysql_admin_table() which re-uses same table list
  element several times with different types of table-level
  and metadata locks.
  We now also properly initialize MDL_request objects for table
  list elements which are later passed to lock_table_names()
  function.
sql/table.cc:
  Do not reset type of MDL_request between statement
  re-executions. This became unnecessesary as we no longer
  change type of MDL_request residing in table list element.
  In its turn this change allows to set type of MDL_request
  only once - at parsing time.
sql/table.h:
  Got rid of TABLE_LIST::EXCLUSIVE_MDL lock strategy.
  Now we can specify that we need to acquire exclusive lock
  on table to be processed by open_tables() through setting
  an appropriate type of MDL_request at parsing time (this
  became possible thanks to the fact that we no longer reset
  types of MDL_request's belonging to table list elements
  between statement re-execution).
  Strategy SHARED_MDL was renamed to OTLS_NONE as now it
  means that metadata lock should not be changed during call
  to open_table() (if it has been already acquired) and is
  also used for exclusive metadata lock.
  Strategy EXCLUSIVE_DOWNGRADABLE_MDL was renamed to
  OTLS_DOWNGRADE_IF_EXISTS.
2010-05-25 16:35:01 +04:00
Alexey Kopytov
c2ebb0ac88 Bug #42064: low memory crash when importing hex strings, in
Item_hex_string::Item_hex_string

The status of memory allocation in the Lex_input_stream (called
from the Parser_state constructor) was not checked which led to
a parser crash in case of the out-of-memory error.

The solution is to introduce new init() member function in
Parser_state and Lex_input_stream so that status of memory
allocation can be returned to the caller.

mysql-test/r/error_simulation.result:
  Added a test case for bug #42064.
mysql-test/t/error_simulation.test:
  Added a test case for bug #42064.
mysys/my_alloc.c:
  Added error injection code for the regression test.
mysys/my_malloc.c:
  Added error injection code for the regression test.
mysys/safemalloc.c:
  Added error injection code for the regression test.
sql/event_data_objects.cc:
  Use the new init() member function of Parser_state and check
  its return value to handle memory allocation failures.
sql/mysqld.cc:
  Added error injection code for the regression test.
sql/sp.cc:
  Use the new init() member function of Parser_state and check
  its return value to handle memory allocation failures.
sql/sql_lex.cc:
  Moved memory allocation from constructor to the separate init()
  member function.
  Added error injection code for the regression test.
sql/sql_lex.h:
  Moved memory allocation from constructor to the separate init()
  member function.
sql/sql_parse.cc:
  Use the new init() member function of Parser_state and check
  its return value to handle memory allocation failures.
sql/sql_partition.cc:
  Use the new init() member function of Parser_state and check
  its return value to handle memory allocation failures.
sql/sql_prepare.cc:
  Use the new init() member function of Parser_state and check
  its return value to handle memory allocation failures.
sql/sql_trigger.cc:
  Use the new init() member function of Parser_state and check
  its return value to handle memory allocation failures.
sql/sql_view.cc:
  Use the new init() member function of Parser_state and check
  its return value to handle memory allocation failures..
sql/thr_malloc.cc:
  Added error injection code for the regression test.
2010-05-21 15:23:48 +04:00
Konstantin Osipov
1ab519d91f Committing on behalf or Dmitry Lenev:
Fix for bug #46947 "Embedded SELECT without FOR UPDATE is
causing a lock", with after-review fixes.

SELECT statements with subqueries referencing InnoDB tables
were acquiring shared locks on rows in these tables when they
were executed in REPEATABLE-READ mode and with statement or
mixed mode binary logging turned on.

This was a regression which were introduced when fixing
bug 39843.

The problem was that for tables belonging to subqueries
parser set TL_READ_DEFAULT as a lock type. In cases when
statement/mixed binary logging at open_tables() time this
type of lock was converted to TL_READ_NO_INSERT lock at
open_tables() time and caused InnoDB engine to acquire
shared locks on reads from these tables. Although in some
cases such behavior was correct (e.g. for subqueries in
DELETE) in case of SELECT it has caused unnecessary locking.

This patch tries to solve this problem by rethinking our
approach to how we handle locking for SELECT and subqueries.
Now we always set TL_READ_DEFAULT lock type for all cases
when we read data. When at open_tables() time this lock
is interpreted as TL_READ_NO_INSERT or TL_READ depending
on whether this statement as a whole or call to function
which uses particular table should be written to the
binary log or not (if yes then statement should be properly
serialized with concurrent statements and stronger lock
should be acquired).

Test coverage is added for both InnoDB and MyISAM.

This patch introduces an "incompatible" change in locking
scheme for subqueries used in SELECT ... FOR UPDATE and
SELECT .. IN SHARE MODE.
In 4.1 the server would use a snapshot InnoDB read for 
subqueries in SELECT FOR UPDATE and SELECT .. IN SHARE MODE
statements, regardless of whether the binary log is on or off.
If the user required a different type of read (i.e. locking read),
he/she could request so explicitly by providing FOR UPDATE/IN SHARE MODE
clause for each individual subquery.
On of the patches for 5.0 broke this behaviour (which was not documented
or tested), and started to use locking reads fora all subqueries in SELECT ... 
FOR UPDATE/IN SHARE MODE. This patch restored 4.1 behaviour.

mysql-test/include/check_concurrent_insert.inc:
  Added auxiliary script which allows to check if statement
  reading table allows concurrent inserts in it.
mysql-test/include/check_no_concurrent_insert.inc:
  Added auxiliary script which allows to check that statement
  reading table doesn't allow concurrent inserts in it.
mysql-test/include/check_no_row_lock.inc:
  Added auxiliary script which allows to check if statement
  reading table doesn't take locks on its rows.
mysql-test/include/check_shared_row_lock.inc:
  Added auxiliary script which allows to check if statement
  reading table takes shared locks on some of its rows.
mysql-test/r/bug39022.result:
  After bug #46947 'Embedded SELECT without FOR UPDATE is
  causing a lock' was fixed test case for bug 39022 has to
  be adjusted in order to trigger execution path on which
  original problem was encountered.
mysql-test/r/innodb_mysql_lock2.result:
  Added coverage for handling of locking in various cases when
  we read data from InnoDB tables (includes test case for
  bug #46947 'Embedded SELECT without FOR UPDATE is causing a
  lock').
mysql-test/r/lock_sync.result:
  Added coverage for handling of locking in various cases when
  we read data from MyISAM tables.
mysql-test/t/bug39022.test:
  After bug #46947 'Embedded SELECT without FOR UPDATE is
  causing a lock' was fixed test case for bug 39022 has to
  be adjusted in order to trigger execution path on which
  original problem was encountered.
mysql-test/t/innodb_mysql_lock2.test:
  Added coverage for handling of locking in various cases when
  we read data from InnoDB tables (includes test case for
  bug #46947 'Embedded SELECT without FOR UPDATE is causing a
  lock').
mysql-test/t/lock_sync.test:
  Added coverage for handling of locking in various cases when
  we read data from MyISAM tables.
sql/log_event.cc:
  Since LEX::lock_option member was removed we no longer can
  rely on its value in Load_log_event::print_query() to
  determine that log event correponds to LOAD DATA CONCURRENT
  statement (this was not correct in all situations anyway).
  A new Load_log_event's member was introduced as a replacement.
  It is initialized at event object construction time and
  explicitly indicates whether LOAD DATA was concurrent.
sql/log_event.h:
  Since LEX::lock_option member was removed we no longer can
  rely on its value in Load_log_event::print_query() to
  determine that log event correponds to LOAD DATA CONCURRENT
  statement (this was not correct in all situations anyway).
  A new Load_log_event's member was introduced as a replacement.
  It is initialized at event object construction time and
  explicitly indicates whether LOAD DATA was concurrent.
sql/sp_head.cc:
  sp_head::reset_lex():
    Before parsing substatement reset part of parser state
    which needs this (e.g. set Yacc_state::m_lock_type to
    default value).
sql/sql_acl.cc:
  Since LEX::reset_n_backup_query_tables_list() now also
  resets LEX::sql_command member (as it became part of
  Query_tables_list class) we have to restore it in cases
  when while working with proxy Query_table_list we assume
  that LEX::sql_command still corresponds to original SQL
  command being executed (for example, when we are logging
  statement to the binary log while having Query_tables_list
  reset and backed up).
sql/sql_base.cc:
  Changed read_lock_type_for_table() to return a weak TL_READ
  type of lock in cases when we are executing statement which
  won't update tables directly and table doesn't belong to
  statement's prelocking list and thus can't be used by a
  stored function. It is OK to do so since in this case table
  won't be used by statement or function call which will be
  written to the binary log, so serializability requirements
  for it can be relaxed.
  One of results from this change is that SELECTs on InnoDB
  tables no longer takes shared row locks for tables which
  are used in subqueries (i.e. bug #46947 is fixed).
  Another result is that for similar SELECTs on MyISAM tables
  concurrent inserts are allowed.
  In order to implement this change signature of
  read_lock_type_for_table() function was changed to take
  pointers to Query_tables_list and TABLE_LIST objects.
sql/sql_base.h:
  - Function read_lock_type_for_table() now takes pointers
    to Query_tables_list and TABLE_LIST elements as its
    arguments since to correctly determine lock type it needs
    to know what statement is being performed and whether table
    element for which lock type to be determined belongs to
    prelocking list.
sql/sql_lex.cc:
  - Removed LEX::lock_option and st_select_lex::lock_option
    members. Places in parser that were using them now use
    Yacc_state::m_lock_type instead.
  - To emphasize that LEX::sql_command member is used during
    process of opening and locking of tables it was moved to
    Query_tables_list class. It is now reset by
    Query_tables_list::reset_query_tables_list() method.
sql/sql_lex.h:
  - Removed st_select_lex::lock_option member as there is no
    real need for per-SELECT lock type (HIGH_PRIORITY option
    should apply to the whole statement. FOR UPDATE/LOCK IN
    SHARE MODE clauses can be handled without this member).
    The main effect which was achieved by introduction of this
    member, i.e. using TL_READ_DEFAULT lock type for
    subqueries, is now achieved by setting LEX::lock_option
    (or rather its replacement - Yacc_state::m_lock_type) to
    TL_READ_DEFAULT in almost all cases.
  - To emphasize that LEX::sql_command member is used during
    process of opening and locking of tables it was moved to
    Query_tables_list class.
  - Replaced LEX::lock_option with Yacc_state::m_lock_type
    in order to emphasize that this value is relevant only
    during parsing. Unlike for LEX::lock_option the default
    value for Yacc_state::m_lock_type is TL_READ_DEFAULT.
    Note that for cases when it is OK to take a "weak" read
    lock (e.g. simple SELECT) this lock type will be converted
    to TL_READ at open_tables() time. So this change won't
    cause negative change in behavior for such statements.
    OTOH this change ensures that, for example, for SELECTs
    which are used in stored functions TL_READ_NO_INSERT lock
    is taken when necessary and as result calls to such stored
    functions can be written to the binary log with correct
    serialization.
sql/sql_load.cc:
  Load_log_event constructor now requires a parameter that
  indicates whether LOAD DATA is concurrent.
sql/sql_parse.cc:
  LEX::lock_option was replaced with Yacc_state::m_lock_type.
  And instead of resetting the latter implicitly in
  mysql_init_multi_delete() we do it explicitly in the
  places in parser which call this function.
sql/sql_priv.h:
  - To be able more easily distinguish high-priority SELECTs
    in st_select_lex::print() method added flag for
    HIGH_PRIORITY option.
sql/sql_select.cc:
  Changed code not to rely on LEX::lock_option to determine
  that it is high-priority SELECT. It was replaced with
  Yacc_state::m_lock_type which is accessible only at
  parse time. So instead of LEX::lock_option we now rely
  on a newly introduced flag for st_select_lex::options -
  SELECT_HIGH_PRIORITY.
sql/sql_show.cc:
  Since LEX::reset_n_backup_query_tables_list() now also
  resets LEX::sql_command member (as it became part of
  Query_tables_list class) we have to restore it in cases
  when while working with proxy Query_table_list we assume
  that LEX::sql_command still corresponds to original SQL
  command being executed.
sql/sql_table.cc:
  Since LEX::reset_query_tables_list() now also resets
  LEX::sql_command member (as it became part of
  Query_tables_list class) we have to restore value of this
  member when this method is called by mysql_admin_table(),
  to make this code safe for re-execution.
sql/sql_trigger.cc:
  Since LEX::reset_n_backup_query_tables_list() now also
  resets LEX::sql_command member (as it became part of
  Query_tables_list class) we have to restore it in cases
  when while working with proxy Query_table_list we assume
  that LEX::sql_command still corresponds to original SQL
  command being executed (for example, when we are logging
  statement to the binary log while having Query_tables_list
  reset and backed up).
sql/sql_update.cc:
  Function read_lock_type_for_table() now takes pointers
  to Query_tables_list and TABLE_LIST elements as its
  arguments since to correctly determine lock type it needs
  to know what statement is being performed and whether table
  element for which lock type to be determined belongs to
  prelocking list.
sql/sql_yacc.yy:
  - Removed st_select_lex::lock_option member as there is no
    real need for per-SELECT lock type (HIGH_PRIORITY option
    should apply to the whole statement. FOR UPDATE/LOCK IN
    SHARE MODE clauses can be handled without this member).
    The main effect which was achieved by introduction of this
    member, i.e. using TL_READ_DEFAULT lock type for
    subqueries, is now achieved by setting LEX::lock_option
    (or rather its replacement - Yacc_state::m_lock_type) to
    TL_READ_DEFAULT in almost all cases.
  - Replaced LEX::lock_option with Yacc_state::m_lock_type
    in order to emphasize that this value is relevant only
    during parsing. Unlike for LEX::lock_option the default
    value for Yacc_state::m_lock_type is TL_READ_DEFAULT.
    Note that for cases when it is OK to take a "weak" read
    lock (e.g. simple SELECT) this lock type will be converted
    to TL_READ at open_tables() time. So this change won't
    cause negative change in behavior for such statements.
    OTOH this change ensures that, for example, for SELECTs
    which are used in stored functions TL_READ_NO_INSERT lock
    is taken when necessary and as result calls to such stored
    functions can be written to the binary log with correct
    serialization.
  - To be able more easily distinguish high-priority SELECTs
    in st_select_lex::print() method we now use new flag
    in st_select_lex::options bit-field.
2010-04-28 14:04:11 +04:00
Mats Kindahl
46bd78b9ee WL#5030: Splitting mysql_priv.h
Adding my_global.h first in all files using
NO_EMBEDDED_ACCESS_CHECKS.

Correcting a merge problem resulting from a changed definition
of check_some_access compared to the original patches.
2010-04-07 13:58:40 +02: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
Alexander Nozdrin
b3018e8613 Manual merge from mysql-trunk-merge.
Conflicts:
  - client/mysql.cc
  - client/mysqldump.c
  - configure.in
  - mysql-test/r/csv.result
  - mysql-test/r/func_time.result
  - mysql-test/r/show_check.result
  - mysql-test/r/sp-error.result
  - mysql-test/r/sp.result
  - mysql-test/r/sp_trans.result
  - mysql-test/r/type_blob.result
  - mysql-test/r/type_timestamp.result
  - mysql-test/r/warnings.result
  - mysql-test/suite/rpl/r/rpl_sp.result
  - sql/mysql_priv.h
  - sql/mysqld.cc
  - sql/sp.cc
  - sql/sql_base.cc
  - sql/sql_table.cc
  - sql/sql_trigger.cc
  - sql/sql_view.cc
  - sql/table.h
  - sql/share/errmsg.txt
  - mysql-test/suite/sys_vars/r/log_bin_trust_routine_creators_basic.result
2010-02-24 16:52:27 +03:00
Alexey Kopytov
0afa209018 Manual merge of mysql-5.1-bugteam to mysql-trunk-merge. 2010-02-22 00:33:11 +03:00
Konstantin Osipov
00dc9a6e70 Merge next-mr -> next-4284.
Cherry-pick a fix Bug#37148 from next-mr, to preserve
file ids of the added files, and ensure that all the necessary
changes have been pulled.

Since initially Bug#37148 was null-merged into 6.0,
the changeset that is now being cherry-picked was likewise
null merged into next-4284.

Now that Bug#37148 has been reapplied to 6.0, try to make
it work with next-4284. This is also necessary to be able
to pull other changes from 5.1-rep into next-4284.

To resolve the merge issues use this changeset applied
to 6.0:
revid:jperkin@sun.com-20091216103628-ylhqf7s6yegui2t9
revno: 3776.1.1
committer: He Zhenxing <zhenxing.he@sun.com>
branch nick: 6.0-codebase-bugfixing
timestamp: Thu 2009-12-17 17:02:50 +0800
message:
  Fix merge problem with Bug#37148
2010-02-04 23:15:47 +03:00
Konstantin Osipov
f30d17e078 Merge next-mr -> next-4284. 2010-02-04 00:48:40 +03:00
Konstantin Osipov
c8555bdb35 Merge next-mr -> next-4284 2010-02-03 16:43:03 +03: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
Alexander Nozdrin
5aa4c33e32 Manual merge from mysql-5.1-bugteam.
Conflicts:
  - sql/mysql_priv.h
2010-01-30 21:47:11 +03:00
Davi Arnaut
d6ab925c5e Bug#50423: Crash on second call of a procedure dropping a trigger
The problem was that a DROP TRIGGER statement inside a stored
procedure could cause a crash in subsequent invocations. This
was due to the addition, on the first execution, of a temporary
table reference to the stored procedure query table list. In
a subsequent invocation, there would be a attempt to reinitialize
the temporary table reference, which by then was already gone.

The solution is to backup and reset the query table list each
time a trigger needs to be dropped. This ensures that any temp
changes to the query table list are discarded. It is safe to
do so at this time as drop trigger is restricted from more
complicated scenarios (ie, not allowed within stored functions,
etc).

mysql-test/r/sp-bugs.result:
  Add test case result for Bug#50423
mysql-test/t/sp-bugs.test:
  Add test case for Bug#50423
sql/sql_trigger.cc:
  Backup and reset the query table list.
  Remove now unnecessary manual reset of the query table list.
2010-01-28 12:41:14 -02:00
He Zhenxing
2b16517522 Backport Bug#37148 to 5.1 2010-01-24 15:03:23 +08:00
Sergey Glukhov
5a4a98af14 backported:
-WL#2822 INFORMATION_SCHEMA.ROUTINES: Add missing columns
-WL#2003 INFORMATION_SCHEMA: PARAMETERS view
-addon for 'I_S optimization' WL
2010-01-15 15:42:15 +04:00
Marc Alff
3d91522561 WL#2360 Performance schema
Part IV: sql instrumentation
2010-01-06 22:42:07 -07:00
Marc Alff
0531f85e16 Merge cleanup 2009-12-11 12:45:44 -07:00
Marc Alff
bea4ab9bb6 Merge mysql-next-mr (revno 2936) --> mysql-next-mr-marc 2009-12-11 01:58:13 -07:00
Jon Olav Hauglid
5e1dfa4c06 Backport of revno: 2617.71.1
Bug#42546 Backup: RESTORE fails, thinking it finds an existing table

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

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

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

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

Fixing the issue for ALTER TABLE RENAME is beyond the scope of this
patch. ALTER TABLE cannot be prohibited from working under LOCK TABLES
as this could seriously impact customers and a proper fix would require
a significant rewrite.
2009-12-10 11:53:20 +01:00
Konstantin Osipov
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
Konstantin Osipov
634a810942 Backport of:
------------------------------------------------------------
revno: 2617.68.24
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-next-bg-pre2-2
timestamp: Wed 2009-09-16 17:25:29 +0400
message:
  Pre-requisite patch for fixing bug #30977 "Concurrent statement
  using stored function and DROP FUNCTION breaks SBR".

  Added MDL_request for stored routine as member to Sroutine_hash_entry
  in order to be able perform metadata locking for stored routines in
  future (Sroutine_hash_entry is an equivalent of TABLE_LIST class for
  stored routines).
(WL#4284, follow up fixes).

sql/mdl.cc:
  Introduced version of MDL_request::init() method which initializes
  lock request using pre-built MDL key.
  MDL_key::table_name/table_name_length() getters were
  renamed to reflect the fact that MDL_key objects are
  now created not only for tables.
sql/mdl.h:
  Extended enum_mdl_namespace enum with values which correspond
  to namespaces for stored functions and triggers.
  Renamed MDL_key::table_name/table_name_length() getters
  to MDL_key::name() and name_length() correspondingly to
  reflect the fact that MDL_key objects are now created
  not only for tables.
  Added MDL_key::mdl_namespace() getter.
  Also added version of MDL_request::init() method which
  initializes lock request using pre-built MDL key.
sql/sp.cc:
  Added MDL_request for stored routine as member to Sroutine_hash_entry.
  Changed code to use MDL_key from this request as a key for LEX::sroutines
  set. Removed separate "key" member from Sroutine_hash_entry as it became
  unnecessary.
sql/sp.h:
  Added MDL_request for stored routine as member to Sroutine_hash_entry
  in order to be able perform metadata locking for stored routines in
  future (Sroutine_hash_entry is an equivalent of TABLE_LIST class for
  stored routines).
  Removed Sroutine_hash_entry::key member as now we can use MDL_key from
  this request as a key for LEX::sroutines set.
sql/sp_head.cc:
  Removed sp_name::m_sroutines_key member and set_routine_type() method.
  Since key for routine in LEX::sroutines set has no longer sp_name::m_qname
  as suffix we won't save anything by creating it at sp_name construction
  time.
  Adjusted sp_name constructor used for creating temporary objects for
  lookups in SP-cache to accept MDL_key as parameter and to avoid any
  memory allocation.
  Finally, removed sp_head::m_soutines_key member for reasons similar
  to why sp_name::m_sroutines_key was removed
sql/sp_head.h:
  Removed sp_name::m_sroutines_key member and set_routine_type() method.
  Since key for routine in LEX::sroutines set has no longer sp_name::m_qname
  as suffix we won't save anything by creating it at sp_name construction
  time.
  Adjusted sp_name constructor used for creating temporary objects for
  lookups in SP-cache to accept MDL_key as parameter and to avoid any
  memory allocation.
  Finally, removed sp_head::m_soutines_key member for reasons similar
  to why sp_name::m_sroutines_key was removed.
sql/sql_base.cc:
  Adjusted code to the fact that we now use MDL_key from
  Sroutine_hash_entry::mdl_request as a key for LEX::sroutines set.
  MDL_key::table_name/table_name_length() getters were
  renamed to reflect the fact that MDL_key objects are
  now created not only for tables.
sql/sql_trigger.cc:
  sp_add_used_routine() now takes MDL_key as parameter as now we use
  instance of this class as a key for LEX::sroutines set.
2009-12-09 19:11:26 +03:00
Jon Olav Hauglid
f3e9b392ac Backport of revno: 2617.68.13
Introduce a counter for protection against global read lock on thread level.

The functions for protection against global read lock sometimes need a local
variable to signal when the protection is set, and hence need to be released.
It would be better to control this behaviour via a counter on the THD struct,
telling how many times the protection has been claimed by the current thread.
A side-effect of the fix is that if protection is claimed twice for a thread,
only a simple increment is required for the second claim, instead of a
mutex-protected increment of the global variable protect_against_global_read_lock.


sql/lock.cc:
  Count how many times that we have claimed protection against global read lock.
  Assert that we really have the protection when releasing it.
  Added comments to all functions operating on global_read_lock.
sql/sql_class.cc:
  Added the counter variable global_read_lock_protection.
sql/sql_class.h:
  Added the counter variable global_read_lock_protection.
sql/sql_parse.cc:
  Replaced test on local variable need_start_waiting with test on
  thd->global_read_lock_protection.
sql/sql_table.cc:
  Replaced test on local variable need_start_waiting with test on
  thd->global_read_lock_protection.
sql/sql_trigger.cc:
  Inserted test on thd->global_read_lock_protection.
2009-12-09 15:25:48 +01:00
Konstantin Osipov
59f82702a1 Backport of:
------------------------------------------------------------
revno: 2617.69.32
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-next-bg46747
timestamp: Wed 2009-08-19 18:12:27 +0400
message:
  Fix for bug #46747 "Crash in MDL_ticket::upgrade_shared_lock_to_exclusive
  on TRIGGER + TEMP table".

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

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

  This fix ensures that DROP TRIGGER ignores temporary tables when
  trying to open table on which trigger to be dropped is defined.


mysql-test/r/trigger.result:
  Added test case for bug #46747 "Crash in
  MDL_ticket::upgrade_shared_lock_to_exclusive
  on TRIGGER + TEMP table".
mysql-test/t/trigger.test:
  Added test case for bug #46747 "Crash in
  MDL_ticket::upgrade_shared_lock_to_exclusive
  on TRIGGER + TEMP table".
sql/sql_trigger.cc:
  Prevent DROP TRIGGER from opening temporary table which might
  shadow base table on which trigger to be dropped is defined.
2009-12-09 12:37:54 +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
Konstantin Osipov
302352723e Backport of:
----------------------------------------------------------
revno: 2617.69.24
committer: Konstantin Osipov <kostja@sun.com>
branch nick: 5.4-42546
timestamp: Fri 2009-08-14 19:22:05 +0400
message:
  A pre-requisite for a fix for Bug#42546 "Backup: RESTORE fails, thinking it
  finds an existing table"
  Back-port from WL 148 "Foreign keys" feature tree a patch
  that introduced Prelocking_strategy class -- a way to parameterize
  open_tables() behaviour, implemented by Dmitry Lenev.

(Part of WL#4284).

sql/sql_base.cc:
  Implement different prelocking strategies. Use an instance of
  prelocking_strategy in open_tables().
sql/sql_class.h:
  Add declarations for class Prelocking_strategy.
sql/sql_lex.h:
  Add a helper method to access last table of the global table list
  (lex->query_tables).
sql/sql_parse.cc:
  Use a special prelocking strategy when locking tables for LOCK TABLES.
sql/sql_table.cc:
  Use normal open_and_lock_tables_derived() in ALTER TABLE.
sql/sql_yacc.yy:
  Modify the grammar to not pollute the global table list with tables
  that should not be opened.
2009-12-08 17:13:12 +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
3104af49cd Backport of:
----------------------------------------------------------
revno: 2630.10.1
committer: Konstantin Osipov <konstantin@mysql.com>
branch nick: mysql-6.0-lock-tables-tidyup
timestamp: Wed 2008-06-11 15:49:58 +0400
message:
  WL#3726, review fixes.
  Now that we have metadata locks, we don't need to keep a crippled
  TABLE instance in the table cache to indicate that a table is locked.
  Remove all code that used this technique. Instead, rely on metadata
  locks and use the standard open_table() and close_thread_table()
  to manipulate with the table cache tables.
  Removes a list of functions that have become unused (see the comment
  for sql_base.cc for details).
  Under LOCK TABLES, keep a TABLE_LIST instance for each table
  that may be temporarily closed. For that, implement an own class for
  LOCK TABLES mode, Locked_tables_list.

This is a pre-requisite patch for WL#4144.
This is not exactly a backport: there is no new 
online ALTER table in Celosia, so the old alter table
code was changed to work with the new table cache API.


mysql-test/r/lock.result:
  Update results (WL#3726 post-review patch).
mysql-test/r/trigger-compat.result:
  We take the table from the table cache now, thus no warning.
mysql-test/suite/rpl/r/rpl_trigger.result:
  We take the table from the table cache now, thus no warning.
mysql-test/t/lock.test:
  Additional tests for LOCK TABLES mode (previously not covered by
  the test suite (WL#3726).
sql/field.h:
  Remove reopen_table().
sql/lock.cc:
  Remove an obsolete parameter of mysql_lock_remove().
  It's not used anywhere now either.
sql/mysql_priv.h:
  Add 4 new open_table() flags.
  Remove declarations of removed functions.
sql/sp_head.cc:
  Rename thd->mdl_el_root to thd->locked_tables_root.
sql/sql_acl.cc:
  Use the new implementation of unlock_locked_tables().
sql/sql_base.cc:
  Implement class Locked_tables_list.
  Implement close_all_tables_for_name().
  Rewrite close_cached_tables() to use the new reopen_tables().
  Remove reopen_table(), reopen_tables(), reopen_table_entry() 
  (ex. open_unireg_entry()), close_data_files_and_leave_as_placeholders(),
  close_handle_and_leave_table_as_placeholder(), close_cached_table(),
  table_def_change_share(), reattach_merge(), reopen_name_locked_table(),
  unlink_open_table().
  
  Move acquisition of a metadata lock into an own function
  - open_table_get_mdl_lock().
sql/sql_class.cc:
  Deploy class Locked_tables_list.
sql/sql_class.h:
  Declare class Locked_tables_list.
  Keep one instance of this class in class THD.
  Rename mdl_el_root to locked_tables_root.
sql/sql_db.cc:
  Update a comment.
sql/sql_insert.cc:
  Use the plain open_table() to open a just created table in
  CREATE TABLE .. SELECT.
sql/sql_parse.cc:
  Use thd->locked_tables_list to enter and leave LTM_LOCK_TABLES mode.
sql/sql_partition.cc:
  Deploy the new method of working with partitioned table locks.
sql/sql_servers.cc:
  Update to the new signature of unlock_locked_tables().
sql/sql_table.cc:
  In mysql_rm_table_part2(), the branch that removes a table under
  LOCK TABLES, make sure that the table being dropped
  is also removed from THD::locked_tables_list.
  Update ALTER TABLE and CREATE TABLE LIKE implementation to use
  open_table() and close_all_tables_for_name() instead of 
  reopen_tables().
sql/sql_trigger.cc:
  Use the new locking way.
sql/table.h:
  Add TABLE::pos_in_locked_tables, which is used only under
  LOCK TABLES.
2009-12-02 18:22:15 +03:00
Konstantin Osipov
e8a9191e64 Backport of:
------------------------------------------------------------
revno: 2630.9.3
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w3
timestamp: Wed 2008-06-11 08:33:36 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After review fixes in progress.

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

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

  After-review fixes in progress.

  Minor changes in order to improve code readability
  and simplify debugging.


mysql-test/r/ps_ddl.result:
  Restore the original (correct) behaviour,
  now that the patch that fixes the regression
  introduced by the original patch for WL#3726 is fixed.
mysql-test/t/ps_ddl.test:
  Restore the original (correct) behaviour,
  now that the patch that fixes the regression
  introduced by the original patch for WL#3726 is fixed
sql/mysql_priv.h:
  Renamed expel_table_from_cache() to tdc_remove_table() 
  and added enum parameter to be able more explicitly specify 
  type of removal.
sql/sql_base.cc:
  Changed close_cached_tables() not to flush all unused TABLE
  instances when flushing individual table.
  Renamed expel_table_from_cache() to tdc_remove_table() and added
  enum parameter to be able more explicitly specify type of
  removal, rewrote its code to be more efficient. As result removed
  relink_unused() function which is no longer used.
  ******
  Improved code in close_cached_tables() according to reviewer's
  comments.
sql/sql_delete.cc:
  Renamed expel_table_from_cache() to tdc_remove_table() 
  and added enum parameter to be able more explicitly 
  specify type of removal.
sql/sql_rename.cc:
  Renamed expel_table_from_cache() to tdc_remove_table() 
  and added enum parameter to be able more explicitly 
  specify type of removal.
sql/sql_show.cc:
  Moved acquisition of high-prio shared metadata lock in which
  happens in fill_schema_table_from_frm() to separate function.
sql/sql_table.cc:
  Renamed expel_table_from_cache() to tdc_remove_table() 
  and added enum parameter to be able more explicitly 
  specify type of removal.
sql/sql_trigger.cc:
  Renamed expel_table_from_cache() to tdc_remove_table() 
  and added enum parameter to be able more explicitly 
  specify type of removal.
2009-12-01 22:13:01 +03:00
Konstantin Osipov
5969dcda21 Backport of:
----------------------------------------------------------
revno: 2630.4.26
committer: Konstantin Osipov <konstantin@mysql.com>
branch nick: mysql-6.0-prelocked_mode-to-push
timestamp: Fri 2008-06-06 23:19:04 +0400
message:
  WL#3726: work on review comments.
  Remove thd->locked_tables. Always store MYSQL_LOCK instances in
  thd->lock.
  Rename thd->prelocked_mode to thd->locked_tables_mode.
  Use thd->locked_tables_mode to determine if we
  are under LOCK TABLES. Update the code to not assume that
  if thd->lock is set, LOCK TABLES mode is off.
  Review comments.


sql/ha_ndbcluster_binlog.cc:
  Don't unlock the lock under LOCK TABLES (safety).
sql/handler.cc:
  There is no thd->locked_tables any more.
  Update comments.
sql/lock.cc:
  There is no thd->locked_tables any more.
sql/log.cc:
  Rename thd->prelocked_mode to thd->locked_tables_mode.
sql/set_var.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sp_head.cc:
  Rename thd->prelocked_mode to thd->locked_tables_mode.
sql/sql_base.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
  Remove thd->locked_tables.
sql/sql_cache.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_class.cc:
  Avoid code duplication.
  Do not release the table locks prematurely if we're under LOCK TABLES.
  Use thd->locked_tables_mode instead of thd->locked_tables.
sql/sql_class.h:
  Remove thd->locked_tables.
  Make prelocked mode a kind of LOCK TABLES mode.
  Update comments.
sql/sql_cursor.cc:
  Update comments.
sql/sql_insert.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
  Rename thd->prelocked_mode to thd->locked_tables_mode.
sql/sql_load.cc:
  Rename thd->prelocked_mode to thd->locked_tables_mode.
sql/sql_parse.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
  Remove thd->locked_tables.
sql/sql_partition.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_rename.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_select.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_table.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_trigger.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_update.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
sql/sql_view.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
storage/myisam/ha_myisam.cc:
  Use thd->locked_tables_mode to determine if we are under LOCK TABLES.
2009-12-01 17:39:03 +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
b05303c132 Backport of:
------------------------------------------------------------
revno: 2630.4.18
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-6.0-3726-w2
timestamp: Tue 2008-06-03 21:07:58 +0400
message:
  WL#3726 "DDL locking for all metadata objects".

  After review fixes in progress.

  Now during upgrading/downgrading metadata locks we deal with
  individual metadata lock requests rather than with all requests
  for this object in the context. This makes API a bit more clear
  and makes adjust_mdl_locks_upgradability() much nicer.


sql/lock.cc:
  lock_table_names():
    Set TABLE_LIST::mdl_lock_data when allocating new metadata
    lock request object for table list element.
sql/mdl.cc:
  Now during upgrading/downgrading metadata locks we deal with
  individual metadata lock requests rather than with all
  requests for this object in the context. Adjusted upgrade/
  downgrade functions accordingly.
  We also got rid of mdl_release_exclusive_locks() and
  now release locks individually. To simplify this process
  mdl_release_all_locks_for_name() was introduced.
sql/mdl.h:
  Now during upgrading/downgrading metadata locks we deal with
  individual metadata lock requests rather than with all
  requests for this object in the context. Adjusted upgrade/
  downgrade functions accordingly.
  We also got rid of mdl_release_exclusive_locks() and
  now release locks individually. To simplify this process
  mdl_release_all_locks_for_name() was introduced.
sql/sql_base.cc:
  Now during upgrading/downgrading metadata locks we deal with
  individual metadata lock requests rather than with all
  requests for this object in the context.
  We also got rid of mdl_release_exclusive_locks() and
  now release locks individually.
sql/sql_parse.cc:
  adjust_mdl_locks_upgradability() is much simplier now due to the
  fact that now during upgrading/downgrading metadata locks we
  deal with individual metadata lock requests rather than with
  all requests for this object in the context.
sql/sql_table.cc:
  Now during upgrading/downgrading metadata locks we deal with
  individual metadata lock requests rather than with all
  requests for this object in the context. Adjusted upgrade/
  downgrade functions accordingly.
  We also got rid of mdl_release_exclusive_locks() and
  now release locks individually. To simplify this process
  mdl_release_all_locks_for_name() was introduced.
sql/sql_trigger.cc:
  ow during upgrading/downgrading metadata locks we deal with
  individual metadata lock requests rather than with all
  requests for this object in the context.
2009-12-01 01:39:13 +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