mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01:00
261 commits
Author | SHA1 | Message | Date | |
---|---|---|---|---|
Bharathy Satish
|
c1fa843d65 |
Bug #17503460 MYSQL READ ONLY DOESN'T WORK FOR DROP TRIGGER
Problem: Drop Trigger succeeds even after setting read_only variable to ON. Fix: Fix is to report the standard error (ER_OPTION_PREVENTS_STATEMENT)when global read_only variable is set to ON. |
||
Murthy Narkedimilli
|
c92223e198 | Updated/added copyright headers | ||
Murthy Narkedimilli
|
8afe262ae5 | Fix for Bug 16395495 - OLD FSF ADDRESS IN GPL HEADER | ||
Kent Boortz
|
789aa8c485 | Updated/added copyright headers | ||
Dmitry Shulga
|
2d715ba604 | Manual-merge of patch for bug#11753738 from mysql-5.1 tree. | ||
Dmitry Shulga
|
1fea8c1b90 |
Fixed bug#11753738 (formely known as bug#45235) - 5.1 DOES NOT SUPPORT 5.0-ONLY
SYNTAX TRIGGERS IN ANY WAY Table with triggers which were using deprecated (5.0-only) syntax became unavailable for any DML and DDL after upgrade to 5.1 version of server. Attempt to execute any statement on such a table resulted in parsing error reported. Since this included DROP TRIGGER and DROP TABLE statements (actually, the latter was allowed but was not functioning properly for such tables) it was impossible to fix the problem without manual operations on .TRG and .TRN files in data directory. The problem was that failure to parse trigger body (due to 5.0-only syntax) when opening trigger file for a table prevented the table from being open. This made all operations on the table impossible (except DROP TABLE which due to peculiarity in its implementation dropped the table but left trigger files around). This patch solves this problem by silencing error which occurs when we parse trigger body during table open. Error message is preserved for the future use and table is marked as having a broken trigger. We also try to analyze parse tree to recover trigger name, which will be needed in order to drop the broken trigger. DML statements which invoke triggers on the table marked as having broken trigger are prohibited and emit saved error message. The same happens for DDL which change triggers except DROP TRIGGER and DROP TABLE which try their best to do what was requested. Table becomes no longer marked as having broken trigger when last such trigger is dropped. mysql-test/r/trigger-compat.result: Add results for test case for bug#45235 mysql-test/t/trigger-compat.test: Add test case for bug#45235. sql/sp_head.cc: Added protection against MEM_ROOT double restoring to sp_head::restore_thd_mem_root() method. Since this method can be sometimes called twice during parsing of stored routine (the first time during normal flow of parsing, and the second time when a syntax error is detected) we need to shortcut execution of the method to avoid damaging MEM_ROOT by the second consecutive call to this method. sql/sql_trigger.cc: Added error handler Deprecated_trigger_syntax_handler to catch non-OOM errors during parsing of trigger body. Added handling of parse errors into method Table_triggers_list::check_n_load(). sql/sql_trigger.h: Added new members to handle broken triggers and error messages. |
||
Alexander Nozdrin
|
060541c02e |
A patch for Bug#11763166 (55847: SHOW WARNINGS returns empty
result set when SQLEXCEPTION is active. The problem was in a hackish THD::no_warnings_for_error attribute. When it was set, an error was not written to Warning_info -- only Diagnostics_area state was changed. That means, Diagnostics_area might contain error state, which is not present in Warning_info. The user-visible problem was that in some cases SHOW WARNINGS returned empty result set (i.e. there were no warnings) while the previous SQL statement failed. According to the MySQL protocol errors must be presented in warning list. The main idea of this patch is to remove THD::no_warnings_for_error. There were few places where it was used: - sql_admin.cc, handling of REPAIR TABLE USE_FRM. - sql_show.cc, when calling fill_schema_table_from_frm(). - sql_show.cc, when calling fill_table(). The fix is to either use internal-error-handlers, or to use temporary Warning_info storing warnings, which might be ignored. This patch is needed to fix Bug 11763162 (55843). |
||
Alexander Nozdrin
|
5653a71d3e |
Patch for Bug#11765684 (58674: SP-cache does not detect changes in
pre-locking list caused by triggers). The thing is that CREATE TRIGGER / DROP TRIGGER may actually change pre-locking list of (some) stored routines. The SP-cache does not detect such changes. Thus if sp_head-instance is cached in SP-cache, subsequent executions of the cached sp_head will use inaccurate pre-locking list. The patch is to invalidate SP-cache on CREATE TRIGGER / DROP TRIGGER. |
||
Jon Olav Hauglid
|
bafe24035d |
Bug #11764779 (former 57649)
FLUSH TABLES under FLUSH TABLES <list> WITH READ LOCK leads to assert failure. This assert was triggered if a statement tried up upgrade a metadata lock with an active FLUSH TABLE <list> WITH READ LOCK. The assert checks that the connection already holds a global intention exclusive metadata lock. However, FLUSH TABLE <list> WITH READ LOCK does not acquire this lock in order to be compatible with FLUSH TABLES WITH READ LOCK. Therefore any metadata lock upgrade caused the assert to be triggered. This patch fixes the problem by preventing metadata lock upgrade if the connection has an active FLUSH TABLE <list> WITH READ LOCK. ER_TABLE_NOT_LOCKED_FOR_WRITE will instead be reported to the client. Test case added to flush.test. |
||
Dmitry Lenev
|
6bf6272fda |
Patch that refactors global read lock implementation and fixes
bug #57006 "Deadlock between HANDLER and FLUSH TABLES WITH READ LOCK" and bug #54673 "It takes too long to get readlock for 'FLUSH TABLES WITH READ LOCK'". The first bug manifested itself as a deadlock which occurred when a connection, which had some table open through HANDLER statement, tried to update some data through DML statement while another connection tried to execute FLUSH TABLES WITH READ LOCK concurrently. What happened was that FTWRL in the second connection managed to perform first step of GRL acquisition and thus blocked all upcoming DML. After that it started to wait for table open through HANDLER statement to be flushed. When the first connection tried to execute DML it has started to wait for GRL/the second connection creating deadlock. The second bug manifested itself as starvation of FLUSH TABLES WITH READ LOCK statements in cases when there was a constant stream of concurrent DML statements (in two or more connections). This has happened because requests for protection against GRL which were acquired by DML statements were ignoring presence of pending GRL and thus the latter was starved. This patch solves both these problems by re-implementing GRL using metadata locks. Similar to the old implementation acquisition of GRL in new implementation is two-step. During the first step we block all concurrent DML and DDL statements by acquiring global S metadata lock (each DML and DDL statement acquires global IX lock for its duration). During the second step we block commits by acquiring global S lock in COMMIT namespace (commit code acquires global IX lock in this namespace). Note that unlike in old implementation acquisition of protection against GRL in DML and DDL is semi-automatic. We assume that any statement which should be blocked by GRL will either open and acquires write-lock on tables or acquires metadata locks on objects it is going to modify. For any such statement global IX metadata lock is automatically acquired for its duration. The first problem is solved because waits for GRL become visible to deadlock detector in metadata locking subsystem and thus deadlocks like one in the first bug become impossible. The second problem is solved because global S locks which are used for GRL implementation are given preference over IX locks which are acquired by concurrent DML (and we can switch to fair scheduling in future if needed). Important change: FTWRL/GRL no longer blocks DML and DDL on temporary tables. Before this patch behavior was not consistent in this respect: in some cases DML/DDL statements on temporary tables were blocked while in others they were not. Since the main use cases for FTWRL are various forms of backups and temporary tables are not preserved during backups we have opted for consistently allowing DML/DDL on temporary tables during FTWRL/GRL. Important change: This patch changes thread state names which are used when DML/DDL of FTWRL is waiting for global read lock. It is now either "Waiting for global read lock" or "Waiting for commit lock" depending on the stage on which FTWRL is. Incompatible change: To solve deadlock in events code which was exposed by this patch we have to replace LOCK_event_metadata mutex with metadata locks on events. As result we have to prohibit DDL on events under LOCK TABLES. This patch also adds extensive test coverage for interaction of DML/DDL and FTWRL. Performance of new and old global read lock implementations in sysbench tests were compared. There were no significant difference between new and old implementations. mysql-test/include/check_ftwrl_compatible.inc: Added helper script which allows to check that a statement is compatible with FLUSH TABLES WITH READ LOCK. mysql-test/include/check_ftwrl_incompatible.inc: Added helper script which allows to check that a statement is incompatible with FLUSH TABLES WITH READ LOCK. mysql-test/include/handler.inc: Adjusted test case to the fact that now DROP TABLE closes open HANDLERs for the table to be dropped before checking if there active FTWRL in this connection. mysql-test/include/wait_show_condition.inc: Fixed small error in the timeout message. The correct name of variable used as parameter for this script is "$condition" and not "$wait_condition". mysql-test/r/delayed.result: Added test coverage for scenario which triggered assert in metadata locking subsystem. mysql-test/r/events_2.result: Updated test results after prohibiting event DDL operations under LOCK TABLES. mysql-test/r/flush.result: Added test coverage for bug #57006 "Deadlock between HANDLER and FLUSH TABLES WITH READ LOCK". mysql-test/r/flush_read_lock.result: Added test coverage for various aspects of FLUSH TABLES WITH READ LOCK functionality. mysql-test/r/flush_read_lock_kill.result: Adjusted test case after replacing custom global read lock implementation with one based on metadata locks. Use new debug_sync point. Do not disable concurrent inserts as now InnoDB we always use InnoDB table. mysql-test/r/handler_innodb.result: Adjusted test case to the fact that now DROP TABLE closes open HANDLERs for the table to be dropped before checking if there active FTWRL in this connection. mysql-test/r/handler_myisam.result: Adjusted test case to the fact that now DROP TABLE closes open HANDLERs for the table to be dropped before checking if there active FTWRL in this connection. mysql-test/r/mdl_sync.result: Adjusted test case after replacing custom global read lock implementation with one based on metadata locks. Replaced usage of GRL-specific debug_sync's with appropriate sync points in MDL subsystem. mysql-test/suite/perfschema/r/dml_setup_instruments.result: Updated test results after removing global COND_global_read_lock condition variable. mysql-test/suite/perfschema/r/func_file_io.result: Ensure that this test doesn't affect subsequent tests. At the end of its execution enable back P_S instrumentation which this test disables at some point. mysql-test/suite/perfschema/r/func_mutex.result: Ensure that this test doesn't affect subsequent tests. At the end of its execution enable back P_S instrumentation which this test disables at some point. mysql-test/suite/perfschema/r/global_read_lock.result: Adjusted test case to take into account that new GRL implementation is based on MDL. mysql-test/suite/perfschema/r/server_init.result: Adjusted test case after replacing custom global read lock implementation with one based on MDL and replacing LOCK_event_metadata mutex with metadata lock. mysql-test/suite/perfschema/t/func_file_io.test: Ensure that this test doesn't affect subsequent tests. At the end of its execution enable back P_S instrumentation which this test disables at some point. mysql-test/suite/perfschema/t/func_mutex.test: Ensure that this test doesn't affect subsequent tests. At the end of its execution enable back P_S instrumentation which this test disables at some point. mysql-test/suite/perfschema/t/global_read_lock.test: Adjusted test case to take into account that new GRL implementation is based on MDL. mysql-test/suite/perfschema/t/server_init.test: Adjusted test case after replacing custom global read lock implementation with one based on MDL and replacing LOCK_event_metadata mutex with metadata lock. mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL.result: Updated test results after prohibiting event DDL under LOCK TABLES. mysql-test/t/delayed.test: Added test coverage for scenario which triggered assert in metadata locking subsystem. mysql-test/t/events_2.test: Updated test case after prohibiting event DDL operations under LOCK TABLES. mysql-test/t/flush.test: Added test coverage for bug #57006 "Deadlock between HANDLER and FLUSH TABLES WITH READ LOCK". mysql-test/t/flush_block_commit.test: Adjusted test case after changing thread state name which is used when COMMIT waits for FLUSH TABLES WITH READ LOCK from "Waiting for release of readlock" to "Waiting for commit lock". mysql-test/t/flush_block_commit_notembedded.test: Adjusted test case after changing thread state name which is used when DML waits for FLUSH TABLES WITH READ LOCK. Now we use "Waiting for global read lock" in this case. mysql-test/t/flush_read_lock.test: Added test coverage for various aspects of FLUSH TABLES WITH READ LOCK functionality. mysql-test/t/flush_read_lock_kill-master.opt: We no longer need to use make_global_read_lock_block_commit_loop debug tag in this test. Instead we rely on an appropriate debug_sync point in MDL code. mysql-test/t/flush_read_lock_kill.test: Adjusted test case after replacing custom global read lock implementation with one based on metadata locks. Use new debug_sync point. Do not disable concurrent inserts as now InnoDB we always use InnoDB table. mysql-test/t/lock_multi.test: Adjusted test case after changing thread state names which are used when DML or DDL waits for FLUSH TABLES WITH READ LOCK to "Waiting for global read lock". mysql-test/t/mdl_sync.test: Adjusted test case after replacing custom global read lock implementation with one based on metadata locks. Replaced usage of GRL-specific debug_sync's with appropriate sync points in MDL subsystem. Updated thread state names which are used when DDL waits for FTWRL. mysql-test/t/trigger_notembedded.test: Adjusted test case after changing thread state names which are used when DML or DDL waits for FLUSH TABLES WITH READ LOCK to "Waiting for global read lock". sql/event_data_objects.cc: Removed Event_queue_element::status/last_executed_changed members and Event_queue_element::update_timing_fields() method. We no longer use this class for updating mysql.events once event is chosen for execution. Accesses to instances of this class in scheduler thread require protection by Event_queue::LOCK_event_queue mutex and we try to avoid updating table while holding this lock. sql/event_data_objects.h: Removed Event_queue_element::status/last_executed_changed members and Event_queue_element::update_timing_fields() method. We no longer use this class for updating mysql.events once event is chosen for execution. Accesses to instances of this class in scheduler thread require protection by Event_queue::LOCK_event_queue mutex and we try to avoid updating table while holding this lock. sql/event_db_repository.cc: - Changed Event_db_repository methods to not release all metadata locks once they are done updating mysql.events table. This allows to keep metadata lock protecting against GRL and lock protecting particular event around until corresponding DDL statement is written to the binary log. - Removed logic for conditional update of "status" and "last_executed" fields from update_timing_fields_for_event() method. In the only case when this method is called now "last_executed" is always modified and tracking change of "status" is too much hassle. sql/event_db_repository.h: Removed logic for conditional update of "status" and "last_executed" fields from Event_db_repository:: update_timing_fields_for_event() method. In the only case when this method is called now "last_executed" is always modified and tracking change of "status" field is too much hassle. sql/event_queue.cc: Changed event scheduler code not to update mysql.events table while holding Event_queue::LOCK_event_queue mutex. Doing so led to a deadlock with a new GRL implementation. This deadlock didn't occur with old implementation due to fact that code acquiring protection against GRL ignored pending GRL requests (which lead to GRL starvation). One of goals of new implementation is to disallow GRL starvation and so we have to solve problem with this deadlock in a different way. sql/events.cc: Changed methods of Events class to acquire protection against GRL while perfoming DDL statement and keep it until statement is written to the binary log. Unfortunately this step together with new GRL implementation exposed deadlock involving Events::LOCK_event_metadata and GRL. To solve it Events::LOCK_event_metadata mutex was replaced with a metadata lock on event. As a side-effect events DDL has to be prohibited under LOCK TABLES even in cases when mysql.events table was explicitly locked for write. sql/events.h: Replaced Events::LOCK_event_metadata mutex with a metadata lock on event. sql/ha_ndbcluster.cc: Updated code after replacing custom global read lock implementation with one based on MDL. Since MDL subsystem should now be able to detect deadlocks involving metadata locks and GRL there is no need for special handling of active GRL. sql/handler.cc: Replaced custom implementation of global read lock with one based on metadata locks. Consequently when doing commit instead of calling method of Global_read_lock class to acquire protection against GRL we simply acquire IX in COMMIT namespace. sql/lock.cc: Replaced custom implementation of global read lock with one based on metadata locks. This step allows to expose wait for GRL to deadlock detector of MDL subsystem and thus succesfully resolve deadlocks similar to one behind bug #57006 "Deadlock between HANDLER and FLUSH TABLES WITH READ LOCK". It also solves problem with GRL starvation described in bug #54673 "It takes too long to get readlock for 'FLUSH TABLES WITH READ LOCK'" since metadata locks used by GRL give preference to FTWRL statement instead of DML statements (if needed in future this can be changed to fair scheduling). Similar to old implementation of acquisition of GRL is two-step. During the first step we block all concurrent DML and DDL statements by acquiring global S metadata lock (each DML and DDL statement acquires global IX lock for its duration). During the second step we block commits by acquiring global S lock in COMMIT namespace (commit code acquires global IX lock in this namespace). Note that unlike in old implementation acquisition of protection against GRL in DML and DDL is semi-automatic. We assume that any statement which should be blocked by GRL will either open and acquires write-lock on tables or acquires metadata locks on objects it is going to modify. For any such statement global IX metadata lock is automatically acquired for its duration. To support this change: - Global_read_lock::lock/unlock_global_read_lock and make_global_read_lock_block_commit methods were changed accordingly. - Global_read_lock::wait_if_global_read_lock() and start_waiting_global_read_lock() methods were dropped. It is now responsibility of code acquiring metadata locks opening tables to acquire protection against GRL by explicitly taking global IX lock with statement duration. - Global variables, mutex and condition variable used by old implementation was removed. - lock_routine_name() was changed to use statement duration for its global IX lock. It was also renamed to lock_object_name() as it now also used to take metadata locks on events. - Global_read_lock::set_explicit_lock_duration() was added which allows not to release locks used for GRL when leaving prelocked mode. sql/lock.h: - Renamed lock_routine_name() to lock_object_name() and changed its signature to allow its usage for events. - Removed broadcast_refresh() function. It is no longer needed with new GRL implementation. sql/log_event.cc: Release metadata locks with statement duration at the end of processing legacy event for LOAD DATA. This ensures that replication thread processing such event properly releases its protection against global read lock. sql/mdl.cc: Changed MDL subsystem to support new MDL-based implementation of global read lock. Added COMMIT and EVENTS namespaces for metadata locks. Changed thread state name for GLOBAL namespace to "Waiting for global read lock". Optimized MDL_map::find_or_insert() method to avoid taking m_mutex mutex when looking up MDL_lock objects for GLOBAL or COMMIT namespaces. We keep pre-created MDL_lock objects for these namespaces around and simply return pointers to these global objects when needed. Changed MDL_lock/MDL_scoped_lock to properly handle notification of insert delayed handler threads when FTWRL takes global S lock. Introduced concept of lock duration. In addition to locks with transaction duration which work in the way which is similar to how locks worked before (i.e. they are released at the end of transaction), locks with statement and explicit duration were introduced. Locks with statement duration are automatically released at the end of statement. Locks with explicit duration require explicit release and obsolete concept of transactional sentinel. * Changed MDL_request and MDL_ticket classes to support notion of duration. * Changed MDL_context to keep locks with different duration in different lists. Changed code handling ticket list to take this into account. * Changed methods responsible for releasing locks to take into account duration of tickets. Particularly public MDL_context::release_lock() method now only can release tickets with explicit duration (there is still internal method which allows to specify duration). To release locks with statement or transaction duration one have to use release_statement/transactional_locks() methods. * Concept of savepoint for MDL subsystem now has to take into account locks with statement duration. Consequently MDL_savepoint class was introduced and methods working with savepoints were updated accordingly. * Added methods which allow to set duration for one or all locks in the context. sql/mdl.h: Changed MDL subsystem to support new MDL-based implementation of global read lock. Added COMMIT and EVENTS namespaces for metadata locks. Introduced concept of lock duration. In addition to locks with transaction duration which work in the way which is similar to how locks worked before (i.e. they are released at the end of transaction), locks with statement and explicit duration were introduced. Locks with statement duration are automatically released at the end of statement. Locks with explicit duration require explicit release and obsolete concept of transactional sentinel. * Changed MDL_request and MDL_ticket classes to support notion of duration. * Changed MDL_context to keep locks with different duration in different lists. Changed code handling ticket list to take this into account. * Changed methods responsible for releasing locks to take into account duration of tickets. Particularly public MDL_context::release_lock() method now only can release tickets with explicit duration (there is still internal method which allows to specify duration). To release locks with statement or transaction duration one have to use release_statement/transactional_locks() methods. * Concept of savepoint for MDL subsystem now has to take into account locks with statement duration. Consequently MDL_savepoint class was introduced and methods working with savepoints were updated accordingly. * Added methods which allow to set duration for one or all locks in the context. sql/mysqld.cc: Removed global mutex and condition variables which were used by old implementation of GRL. Also we no longer need to initialize Events::LOCK_event_metadata mutex as it was replaced with metadata locks on events. sql/mysqld.h: Removed global variable, mutex and condition variables which were used by old implementation of GRL. sql/rpl_rli.cc: When slave thread closes tables which were open for handling of RBR events ensure that it releases global IX lock which was acquired as protection against GRL. sql/sp.cc: Adjusted code to the new signature of lock_object/routine_name(), to the fact that one now needs specify duration of lock when initializing MDL_request and to the fact that savepoints for MDL subsystem are now represented by MDL_savepoint class. sql/sp_head.cc: Ensure that statements in stored procedures release statement metadata locks and thus release their protectiong against GRL in proper moment in time. Adjusted code to the fact that one now needs specify duration of lock when initializing MDL_request. sql/sql_admin.cc: Adjusted code to the fact that one now needs specify duration of lock when initializing MDL_request. sql/sql_base.cc: - Implemented support for new approach to acquiring protection against global read lock. We no longer acquire such protection explicitly on the basis of statement flags. Instead we always rely on code which is responsible for acquiring metadata locks on object to be changed acquiring this protection. This is achieved by acquiring global IX metadata lock with statement duration. Code doing this also responsible for checking that current connection has no active GRL by calling an Global_read_lock::can_acquire_protection() method. Changed code in open_table() and lock_table_names() accordingly. Note that as result of this change DDL and DML on temporary tables is always compatible with GRL (before it was incompatible in some cases and compatible in other cases). - To speed-up code acquiring protection against GRL introduced m_has_protection_against_grl member in Open_table_context class. It indicates that protection was already acquired sometime during open_tables() execution and new attempts can be skipped. - Thanks to new GRL implementation calls to broadcast_refresh() became unnecessary and were removed. - Adjusted code to the fact that one now needs specify duration of lock when initializing MDL_request and to the fact that savepoints for MDL subsystem are now represented by MDL_savepoint class. sql/sql_base.h: Adjusted code to the fact that savepoints for MDL subsystem are now represented by MDL_savepoint class. Also introduced Open_table_context::m_has_protection_against_grl member which allows to avoid acquiring protection against GRL while opening tables if such protection was already acquired. sql/sql_class.cc: Changed THD::leave_locked_tables_mode() after transactional sentinel for metadata locks was obsoleted by introduction of locks with explicit duration. sql/sql_class.h: - Adjusted code to the fact that savepoints for MDL subsystem are now represented by MDL_savepoint class. - Changed Global_read_lock class according to changes in global read lock implementation: * wait_if_global_read_lock and start_waiting_global_read_lock are now gone. Instead code needing protection against GRL has to acquire global IX metadata lock with statement duration itself. To help it new can_acquire_protection() was introduced. Also as result of the above change m_protection_count member is gone too. * Added m_mdl_blocks_commits_lock member to store metadata lock blocking commits. * Adjusted code to the fact that concept of transactional sentinel was obsoleted by concept of lock duration. - Removed CF_PROTECT_AGAINST_GRL flag as it is no longer necessary. New GRL implementation acquires protection against global read lock automagically when statement acquires metadata locks on tables or other objects it is going to change. sql/sql_db.cc: Adjusted code to the fact that one now needs specify duration of lock when initializing MDL_request. sql/sql_handler.cc: Removed call to broadcast_refresh() function. It is no longer needed with new GRL implementation. Adjusted code after introducing duration concept for metadata locks. Particularly to the fact transactional sentinel was replaced with explicit duration. sql/sql_handler.h: Renamed mysql_ha_move_tickets_after_trans_sentinel() to mysql_ha_set_explicit_lock_duration() after transactional sentinel was obsoleted by locks with explicit duration. sql/sql_insert.cc: Adjusted code handling delaying inserts after switching to new GRL implementation. Now connection thread initiating delayed insert has to acquire global IX lock in addition to metadata lock on table being inserted into. This IX lock protects against GRL and similarly to SW lock on table being inserted into has to be passed to handler thread in order to avoid deadlocks. sql/sql_lex.cc: LEX::protect_against_global_read_lock member is no longer necessary since protection against GRL is automatically taken by code acquiring metadata locks/opening tables. sql/sql_lex.h: LEX::protect_against_global_read_lock member is no longer necessary since protection against GRL is automatically taken by code acquiring metadata locks/opening tables. sql/sql_parse.cc: - Implemented support for new approach to acquiring protection against global read lock. We no longer acquire such protection explicitly on the basis of statement flags. Instead we always rely on code which is responsible for acquiring metadata locks on object to be changed acquiring this protection. This is achieved by acquiring global IX metadata lock with statement duration. This lock is automatically released at the end of statement execution. - Changed implementation of CREATE/DROP PROCEDURE/FUNCTION not to release metadata locks and thus protection against of GRL in the middle of statement execution. - Adjusted code to the fact that one now needs specify duration of lock when initializing MDL_request and to the fact that savepoints for MDL subsystem are now represented by MDL_savepoint class. sql/sql_prepare.cc: Adjusted code to the to the fact that savepoints for MDL subsystem are now represented by MDL_savepoint class. sql/sql_rename.cc: With new GRL implementation there is no need to explicitly acquire protection against GRL before renaming tables. This happens automatically in code which acquires metadata locks on tables being renamed. sql/sql_show.cc: Adjusted code to the fact that one now needs specify duration of lock when initializing MDL_request and to the fact that savepoints for MDL subsystem are now represented by MDL_savepoint class. sql/sql_table.cc: - With new GRL implementation there is no need to explicitly acquire protection against GRL before dropping tables. This happens automatically in code which acquires metadata locks on tables being dropped. - Changed mysql_alter_table() not to release lock on new table name explicitly and to rely on automatic release of locks at the end of statement instead. This was necessary since now MDL_context::release_lock() is supported only for locks for explicit duration. sql/sql_trigger.cc: With new GRL implementation there is no need to explicitly acquire protection against GRL before changing table triggers. This happens automatically in code which acquires metadata locks on tables which triggers are to be changed. sql/sql_update.cc: Fix bug exposed by GRL testing. During prepare phase acquire only S metadata locks instead of SW locks to keep prepare of multi-UPDATE compatible with concurrent LOCK TABLES WRITE and global read lock. sql/sql_view.cc: With new GRL implementation there is no need to explicitly acquire protection against GRL before creating view. This happens automatically in code which acquires metadata lock on view to be created. sql/sql_yacc.yy: LEX::protect_against_global_read_lock member is no longer necessary since protection against GRL is automatically taken by code acquiring metadata locks/opening tables. sql/table.cc: Adjusted code to the fact that one now needs specify duration of lock when initializing MDL_request. sql/table.h: Adjusted code to the fact that one now needs specify duration of lock when initializing MDL_request. sql/transaction.cc: Replaced custom implementation of global read lock with one based on metadata locks. Consequently when doing commit instead of calling method of Global_read_lock class to acquire protection against GRL we simply acquire IX in COMMIT namespace. Also adjusted code to the fact that MDL savepoint is now represented by MDL_savepoint class. |
||
Jon Olav Hauglid
|
bf55d1fcf0 | Merge from mysql-5.5-bugteam to mysql-5.5-runtime | ||
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. |
||
Dmitry Shulga
|
029cc52c88 | Auto-merge from mysql-5.1-bugteam. | ||
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. |
||
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. |
||
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(). |
||
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(). |
||
Konstantin Osipov
|
cc6dabba37 | Merge trunk-bugfixing -> trunk-runtime | ||
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 |
||
Alexey Kopytov
|
386929d3ae |
Manual merge from the bugfix tree.
conflicts: conflict sql/sql_parse.cc |
||
Alexey Kopytov
|
e5cf56ef80 |
Manual merge from the bugfix tree.
conflicts: conflict sql/sql_parse.cc |
||
Davi Arnaut
|
db2fe44c84 | Merge of mysql-5.1-bugteam into mysql-trunk-merge. | ||
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. |
||
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). |
||
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. |
||
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. |
||
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. |
||
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. |
||
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 |
||
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 |
||
Alexey Kopytov
|
0afa209018 | Manual merge of mysql-5.1-bugteam to mysql-trunk-merge. | ||
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 |
||
Konstantin Osipov
|
f30d17e078 | Merge next-mr -> next-4284. | ||
Konstantin Osipov
|
c8555bdb35 | Merge next-mr -> next-4284 | ||
Konstantin Osipov
|
665100b69d | Merge next-mr -> next-4284. | ||
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. |
||
Alexander Nozdrin
|
5aa4c33e32 |
Manual merge from mysql-5.1-bugteam.
Conflicts: - sql/mysql_priv.h |
||
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. |
||
He Zhenxing
|
2b16517522 | Backport Bug#37148 to 5.1 | ||
Sergey Glukhov
|
5a4a98af14 |
backported:
-WL#2822 INFORMATION_SCHEMA.ROUTINES: Add missing columns -WL#2003 INFORMATION_SCHEMA: PARAMETERS view -addon for 'I_S optimization' WL |
||
Marc Alff
|
3d91522561 |
WL#2360 Performance schema
Part IV: sql instrumentation |
||
Marc Alff
|
0531f85e16 | Merge cleanup | ||
Marc Alff
|
bea4ab9bb6 | Merge mysql-next-mr (revno 2936) --> mysql-next-mr-marc | ||
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. |
||
Konstantin Osipov
|
f129367288 | Merge with next-4284. | ||
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). |
||
Marc Alff
|
c082955f06 |
WL#2360 Performance schema
Part III: mysys instrumentation |
||
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. |
||
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. |
||
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. |