------------------------------------------------------------
revno: 3258
committer: Jon Olav Hauglid <jon.hauglid@oracle.com>
branch nick: mysql-trunk-bug12663165
timestamp: Thu 2011-07-14 10:05:12 +0200
message:
Bug#12663165 SP DEAD CODE REMOVAL DOESN'T UNDERSTAND CONTINUE HANDLERS
When stored routines are loaded, a simple optimizer tries to locate
and remove dead code. The problem was that this dead code removal
did not work correctly with CONTINUE handlers.
If a statement triggers a CONTINUE handler, the following statement
will be executed after the handler statement has completed. This
means that the following statement is not dead code even if the
previous statement unconditionally alters control flow. This fact
was lost on the dead code removal routine, which ended up with
removing instructions that could have been executed. This could
then lead to assertions, crashes and generally bad behavior when
the stored routine was executed.
This patch fixes the problem by marking as live code all stored
routine instructions that are in the same scope as a CONTINUE handler.
Test case added to sp.test.
There was memory leak when running some tests on PB2.
The reason of the failure is an early return from change_master()
that was supposed to deallocate a dyn-array.
Actually the same bug58915 was fixed in trunk with relocating the dyn-array
destruction into THD::cleanup_after_query() which can't be bypassed.
The current patch backports magne.mahre@oracle.com-20110203101306-q8auashb3d7icxho
and adds two optimizations: were done: the static buffer for the dyn-array to base on,
and the array initialization is called precisely when it's necessary rather than
per each CHANGE-MASTER as before.
mysql-test/suite/rpl/t/rpl_empty_master_host.test:
the test is binlog-format insensitive so it will be run with MIXED mode only.
mysql-test/suite/rpl/t/rpl_server_id_ignore.test:
the test is binlog-format insensitive so it will be run with MIXED mode only.
sql/sql_class.cc:
relocating the dyn-array
destruction into THD::cleanup_after_query().
sql/sql_lex.cc:
LEX.mi zero initialization is done in LEX().
sql/sql_lex.h:
Optimization for repl_ignore_server_ids to base on a static buffer
which size is chosen to fit to most common use cases.
sql/sql_repl.cc:
dyn-array destruction is relocated to THD::cleanup_after_query().
sql/sql_yacc.yy:
Refining logics of Lex->mi.repl_ignore_server_ids initialization.
The array is initialized once a corresponding option in CHANGE MASTER token sequence
is found.
There was memory leak when running some tests on PB2.
The reason of the failure is an early return from change_master()
that was supposed to deallocate a dyn-array.
Fixed with relocating the dyn-array's destructor at ~LEX() that is
the end of the session, per Gleb's patch idea.
Two optimizations were done: the static buffer for the dyn-array to base on,
and the array initialization is called precisely when it's necessary rather than
per each CHANGE-MASTER as before.
mysql-test/suite/rpl/t/rpl_empty_master_host.test:
the test is binlog-format insensitive so it will be run with MIXED mode only.
sql/sql_lex.cc:
the new flag is initialized.
sql/sql_lex.h:
A new bool flag new member to LEX.mi is added to stay UP since after
LEX.mi.repl_ignore_server_ids dynarray initialization was called
for the first time on the session. So it is set once and its life time
is session.
The array is destroyed at the end of the session.
sql/sql_repl.cc:
dyn-array destruction is relocated to ~LEX.
sql/sql_yacc.yy:
Refining logics of Lex->mi.repl_ignore_server_ids initialization.
The array is initialized once a corresponding option in CHANGE MASTER token sequence
is found.
The fact of initialization is memorized into the new flag.
SET STATEMENT.
Server built with debug asserts, without debug crashes if a user tries
to run a stored procedure that constains query with subquery that include
either LIMIT or LIMIT OFFSET clauses.
The problem was that Item::fix_fields() was not called for the items
representing LIMIT or OFFSET clauses.
The solution is to call Item::fix_fields() right before evaluation in
st_select_lex_unit::set_limit().
mysql-test/r/sp.result:
Added testcase result for bug#12621017. Updated testcase result for
bug 11918.
mysql-test/t/sp.test:
Added testcase for bug#12621017. Addressed review comments for Bug 11918
(added tests for use LIMIT at stored function).
sql/item.h:
Addressed review comments for Bug 11918.
sql/share/errmsg-utf8.txt:
Addressed review comments for Bug 11918.
sql/sp_head.cc:
Addressed review comments for Bug 11918.
sql/sql_lex.cc:
Added call fix_fields() for item just before its evaluation.
sql/sql_yacc.yy:
Addressed review comments for Bug 11918.
In 5.5, REFRESH SLAVE is used as an alias for RESET SLAVE and
was removed in 5.6. Reseting a slave through REFRESH SLAVE was
causing errors in the valgrind platform since reset_slave_info
was undefined.
To fix the problem, we have set reset_slave_info while calling
REFRESH SLAVE.
Before BUG#28796, an empty host was used to identify that an instance was no
longer a slave. However, BUG#28796 changed this behavior and one cannot set
an empty host. Besides, a RESET SLAVE only cleans up information on the next
event to retrieve from the master, disables ssl and resets heartbeat period.
So a call to SHOW SLAVE STATUS after issuing a RESET SLAVE still returns some
valid information, such as host, port, user and password.
To fix this problem, we have introduced the command RESET SLAVE ALL that does
what a regular RESET SLAVE does and also clears host, port, user and password
information thus allowing users to identify when an instance is no longer a
slave.
When CREATE TABLE wasn't given ENGINE=... it would determine
the default ENGINE at parse-time rather than at execution
time, leading to incorrect behaviour (namely, later changes
to the default engine being ignore) when calling CREATE TABLE
from a stored procedure.
We now defer working out the default engine till execution of
CREATE TABLE.
mysql-test/r/sp_trans.result:
results!
mysql-test/t/sp_trans.test:
Show that CREATE TABLE (called from store routine) heeds
any changes after CREATE SP / parse-time. Show that explicitly
requesting an ENGINE still works.
sql/sql_parse.cc:
If no ENGINE=... was given at parse-time, determine default
engine at execution time of CREATE TABLE.
sql/sql_yacc.yy:
If CREATE TABLE is not given ENGINE=..., don't bother
figuring out the default engine during parsing; we'll
do it at execution time instead to be aware of the
latest updates.
THE EVENT STATUS.
Any ALTER EVENT statement on a disabled event enabled it back
(unless this ALTER EVENT statement explicitly disabled the event).
The problem was that during processing of an ALTER EVENT statement
value of status field was overwritten unconditionally even if new
value was not specified explicitly. As a consequence this field
was set to default value for status which corresponds to ENABLE.
The solution is to check if status field was explicitly specified in
ALTER EVENT statement before assigning new value to status field.
mysql-test/r/events_bugs.result:
test's result for Bug#11764334 was added.
mysql-test/t/events_bugs.test:
new test for Bug#11764334 was added.
sql/event_db_repository.cc:
mysql_event_fill_row() was modified: set value for status field
in events tables only in case if statement CREATE EVENT
is being processed or if this value was set in ALTER EVENT
statement.
Event_db_repository::create_event was modified: removed redundant
setting of status field after return from call to mysql_event_fill_row().
sql/event_parse_data.h:
Event_parse_data structure was modified: added flag
status_changed that is set to true if status's value
was changed in ALTER EVENT statement.
sql/sql_yacc.yy:
Set flag status_changed if status was set in ALTER EVENT
statement.
SEEMS TO BE 'LEAKING' INTO THE SCHEMA NAME SPACE)
and bug#12428824 (Parser stack overflow and crash in sp_add_used_routine
with obscure query).
The first problem was that attempts to call a stored function by
its fully qualified name ended up with unwarranted error "ERROR 1305
(42000): FUNCTION someMixedCaseDb.my_function_name does not exist"
if this function belonged to a schema that had uppercase letters in
its name AND --lower_case_table_names was equal to either 1 or 2.
The second problem was that 5.5 version of MySQL server might have
crashed when a user tried to call stored function with too long name
or too long database name (i.e if a function and database name combined
occupied more than 2*3*64 bytes in utf8). This issue didn't affect
versions of server < 5.5.
The first problem was caused by the fact that in cases when a stored
function was called by its fully qualified name we didn't lowercase
name of its schema before performing look up of the function in
mysql.proc table even although lower_case_table_names mode was on.
As result we were unable to find this function since during its
creation we store lowercased version of schema name in the system
table in this mode and field for schema name uses binary collation.
Calls to stored functions were unaffected by this problem since for
them schema name is converted to lowercase as necessary.
The reason for the second bug was that MySQL Server didn't check length
of function name and database name before proceeding with execution of
stored function. As a consequence too long database name or function
name caused buffer overruns in places where the code assumes that their
length is within fixed limits, like mdl_key_init() in 5.5.
Again this issue didn't affect calls to stored procedures as for them
length of schema name and procedure name are properly checked.
This patch fixes both these bugs by adding calls to check_db_name()
and check_routine_name() to grammar rule which corresponds to a call
to a stored function. These functions ensure that length of database
name and function name for routine called is within standard limit.
Moreover call to check_db_name() handles conversion of database name
to lowercase if --lower_case_table_names mode is on.
Note that even although the second issue seems to be only reproducible
in 5.5 we still add code fixing it to 5.1 to be on the safe side (and
make code a bit more robust against possible future changes).
mysql-test/r/sp-error.result:
Added testcase results for bug#12428824.
mysql-test/r/sp.result:
Added testcase result for bug#11840395.
mysql-test/t/sp-error.test:
Added testcase for bug#12428824.
mysql-test/t/sp.test:
Added testcase for bug#11840395.
sql/sql_yacc.yy:
Modified 'function_call_generic' rule to call check_db_name() and
check_routine_name() in order to ensure that lengths of database name
and function name are within limits. check_db_name() is also responsible
for normalizing function's database name for lookup in cases when
lowercase_table_names mode is on.
If LOAD DATA INFILE featured a SET clause, the name=value pairs
would be regenerated using item::print. Unfortunately, that code
is mostly optimized for EXPLAIN EXTENDED output and such, and can
not be relied on to return valid SQL.
We now name each value its original, user-supplied form and use
that to create LOAD DATA INFILE statements for statement-based
replication.
mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result:
minor change in syntactic sugar
mysql-test/suite/rpl/r/rpl_loaddatalocal.result:
add test case
mysql-test/suite/rpl/t/rpl_loaddatalocal.test:
add test case
sql/sql_load.cc:
Do not try to item::print values in LOAD DATA INFILE's
SET clause; they might not even be valid SQL at this
point. Use our saved version instead.
sql/sql_yacc.yy:
If LOAD DATA INFILE has SET name=val clauses, tag the
individual val-parts with the user's version so we can
later replicate that, rather than the smashed pieces
we'd get from item::print once the optimizer's through
with our poor values.
MAP 'REPAIR TABLE' TO RECREATE +ANALYZE FOR ENGINES NOT
SUPPORTING NATIVE REPAIR
Executing 'mysqlcheck --check-upgrade --auto-repair ...' will first issue
'CHECK TABLE FOR UPGRADE' for all tables in the database in order to check if the
tables are compatible with the current version of MySQL. Any tables that are
found incompatible are then upgraded using 'REPAIR TABLE'.
The problem was that some engines (e.g. InnoDB) do not support 'REPAIR TABLE'.
This caused any such tables to be left incompatible. As a result such tables were
not properly fixed by the mysql_upgrade tool.
This patch fixes the problem by first changing 'CHECK TABLE FOR UPGRADE' to return
a different error message if the engine does not support REPAIR. Instead of
"Table upgrade required. Please do "REPAIR TABLE ..." it will report
"Table rebuild required. Please do "ALTER TABLE ... FORCE ..."
Second, the patch changes mysqlcheck to do 'ALTER TABLE ... FORCE' instead of
'REPAIR TABLE' in these cases.
This patch also fixes 'ALTER TABLE ... FORCE' to actually rebuild the table.
This change should be reflected in the documentation. Before this patch,
'ALTER TABLE ... FORCE' was unused (See Bug#11746162)
Test case added to mysqlcheck.test
client/mysqlcheck.c:
Changed mysqlcheck to do 'ALTER TABLE ... FORCE' if
'CHECK TABLE FOR UPGRADE' reports ER_TABLE_NEEDS_REBUILD
and not ER_TABLE_NEEDS_UPGRADE.
mysql-test/r/mysqlcheck.result:
Added regression test.
mysql-test/std_data/bug47205.frm:
InnoDB 5.0 FRM which contains a varchar primary key using
utf8_general_ci. This is an incompatible FRM for 5.5.
mysql-test/t/mysqlcheck.test:
Added regression test.
sql/handler.h:
Added new HA_CAN_REPAIR flag.
sql/share/errmsg-utf8.txt:
Added new error message ER_TABLE_NEEDS_REBUILD
sql/sql_admin.cc:
Changed 'CHECK TABLE FOR UPDATE' to give ER_TABLE_NEEDS_REBUILD
instead of ER_TABLE_NEEDS_UPGRADE if the engine does not support
REPAIR (as indicated by the new HA_CAN_REPAIR flag).
sql/sql_lex.h:
Remove unused ALTER_FORCE flag.
sql/sql_yacc.yy:
Make sure ALTER TABLE ... FORCE recreates the table
by setting the ALTER_RECREATE flag as the ALTER_FORCE
flag was unused.
storage/archive/ha_archive.h:
Added new HA_CAN_REPAIR flag to Archive
storage/csv/ha_tina.h:
Added new HA_CAN_REPAIR flag to CSV
storage/federated/ha_federated.h:
Added new HA_CAN_REPAIR flag to Federated
storage/myisam/ha_myisam.cc:
Added new HA_CAN_REPAIR flag to MyISAM
Removes SHOW NEW MASTER statement and all related code.
Also removes the unused function update_slave_list from repl_failsafe.cc.
mysql-test/r/signal_code.result:
Updated result file.
The output of SHOW PROCEDURE CODE has changed, because the numerical values
of some SQLCOM_ commands have changes. This is not a problem, because
SHOW PROCEDURE CODE only exists in debug builds and the numerical values of
SQLCOM_ constants are not exposed elsewhere.
mysql-test/r/sp-code.result:
Updated result file.
The output of SHOW PROCEDURE CODE has changed, because the numerical values
of some SQLCOM_ commands have changes. This is not a problem, because
SHOW PROCEDURE CODE only exists in debug builds and the numerical values of
SQLCOM_ constants are not exposed elsewhere.
sql/mysqld.cc:
Remove SQLCOM_SHOW_NEW_MASTER.
sql/repl_failsafe.cc:
Remove show_new_master, which was only used by the removed SHOW NEW MASTER statement.
Remove translate_master, which was only used by show_new_master.
Remove find_slave_event, which was only used by translate_master.
Remove find_target_pos, which was only used by translate_master.
Remove cmp_master_pos, which was only used by translate_master.
Remove update_slave_list, which was not used at all.
sql/repl_failsafe.h:
Remove declarations of functions removed by this patch:
update_slave_list, show_new_master, translate_master, update_slave_list
Remove declarations of functions that did not exist before this patch:
handle_failsafe_rpl, load_master_data
Remove declaration of function that is static in slave.cc:
connect_to_master
sql/sp_head.cc:
Removed SQLCOM_SHOW_NEW_MASTER
sql/sql_lex.h:
Removed SQLCOM_SHOW_NEW_MASTER
sql/sql_parse.cc:
Removed SQLCOM_SHOW_NEW_MASTER
sql/sql_repl.cc:
Removed cmp_master_pos(char*,ulonglong,char*,ulonglong), which was
only used by cmp_master_pos*Slave_log_event* sev, LEX_MASTER_INFO* mi) in repl_failsafe.cc,
which has been removed.
sql/sql_repl.h:
removed cmp_master_pos
sql/sql_yacc.yy:
removed syntax SHOW NEW MASTER.
and Order By
When having a UNION statement in a subquery, with no
referenced tables (or only a reference to the virtual
table 'dual'), the UNION did not allow an ORDER BY clause.
i.e:
SELECT(SELECT 1 AS a UNION
SELECT 0 AS a
ORDER BY a) AS b or
SELECT(SELECT 1 AS a FROM dual UNION
SELECT 0 as a
ORDER BY a) AS b
In addition, an ORDER BY / LIMIT clause was not accepted
in subqueries even for single SELECT statements with no
referenced tables (or with 'dual' as table reference)
i.e:
SELECT(SELECT 1 AS a ORDER BY a) AS b or
SELECT(SELECT 1 AS a FROM dual ORDER BY a) AS b
The fix was to allow an optional ORDER BY/LIMIT clause to
the grammar for these cases.
See also: Bug#57986
if embedded in a SELECT
An ORDER BY clause was bound to the incorrect
(sub-)statement when used in a UNION context.
In a query like:
SELECT * FROM a UNION SELECT * FROM b ORDER BY c
the result of SELECT * FROM b is sorted, and then
combined with a. The correct behaviour is that
the ORDER BY clause should be applied on the
final set. Similar behaviour was seen on LIMIT
clauses as well.
In a UNION statement, there will be a select_lex
object for each of the two selects, and a
select_lex_unit object that describes the UNION
itself. Similarly, the same behaviour was also
seen on derived tables.
The bug was caused by using a grammar rule for
ORDER BY and LIMIT that bound these elements
to thd->lex->current_select, which points to the
last of the two selects, instead of to the
fake_select_lex member of the master select_lex_unit
object.
sql/sql_yacc.yy:
Need to use (opt_)union_order_or_limit to
bind to the correct select_lex object.
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.
In MySQL 5.5 the new reserved words include:
SLOW as in FLUSH SLOW LOGS
GENERAL as in FLUSH GENERAL LOGS
IGNORE_SERVER_IDS as in CHANGE MASTER ... IGNORE_SERVER_IDS
MASTER_HEARTBEAT_PERIOD as in CHANGE MASTER ... MASTER_HEARTBEAT_PERIOD
These are not reserved words in standard SQL, or in Oracle 11g,
and as such, may affect existing applications.
We fix this by adding the new words to the list of
keywords that are allowed for labels in SPs.
mysql-test/t/keywords.test:
Test case that checks that the target words can be used
for naming fields in a table or as local routine variable
names.
mysql-test/r/grant.result:
It was added result for test case for bug#36742.
mysql-test/t/grant.test:
It was added test case for bug#36742.
sql/sql_yacc.yy:
It was added convertation of host name part of user name to lowercase.
The error message for ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE was
hard coded. Additionally, the same error was used in three
separate error symptoms: 1. when heartbeat period exceeds the
value of slave_net_timeout, 2. when it is smaller than 1
milisecond and 3. when it was not in range, ie, either negative
or greater than the maximum allowed.
We fix this by splitting into three distinct errors and by
removing the message from the source code and moving it to the
errmsg-utf8.txt file.
Bug#54678: InnoDB, TRUNCATE, ALTER, I_S SELECT, crash or deadlock
- Incompatible change: truncate no longer resorts to a row by
row delete if the storage engine does not support the truncate
method. Consequently, the count of affected rows does not, in
any case, reflect the actual number of rows.
- Incompatible change: it is no longer possible to truncate a
table that participates as a parent in a foreign key constraint,
unless it is a self-referencing constraint (both parent and child
are in the same table). To work around this incompatible change
and still be able to truncate such tables, disable foreign checks
with SET foreign_key_checks=0 before truncate. Alternatively, if
foreign key checks are necessary, please use a DELETE statement
without a WHERE condition.
Problem description:
The problem was that for storage engines that do not support
truncate table via a external drop and recreate, such as InnoDB
which implements truncate via a internal drop and recreate, the
delete_all_rows method could be invoked with a shared metadata
lock, causing problems if the engine needed exclusive access
to some internal metadata. This problem originated with the
fact that there is no truncate specific handler method, which
ended up leading to a abuse of the delete_all_rows method that
is primarily used for delete operations without a condition.
Solution:
The solution is to introduce a truncate handler method that is
invoked when the engine does not support truncation via a table
drop and recreate. This method is invoked under a exclusive
metadata lock, so that there is only a single instance of the
table when the method is invoked.
Also, the method is not invoked and a error is thrown if
the table is a parent in a non-self-referencing foreign key
relationship. This was necessary to avoid inconsistency as
some integrity checks are bypassed. This is inline with the
fact that truncate is primarily a DDL operation that was
designed to quickly remove all data from a table.
mysql-test/suite/innodb/t/innodb-truncate.test:
Add test cases for truncate and foreign key checks.
Also test that InnoDB resets auto-increment on truncate.
mysql-test/suite/innodb/t/innodb.test:
FK is not necessary, test is related to auto-increment.
Update error number, truncate is no longer invoked if
table is parent in a FK relationship.
mysql-test/suite/innodb/t/innodb_mysql.test:
Update error number, truncate is no longer invoked if
table is parent in a FK relationship.
Use delete instead of truncate, test is used to check
the interaction of FKs, triggers and delete.
mysql-test/suite/parts/inc/partition_check.inc:
Fix typo.
mysql-test/suite/sys_vars/t/foreign_key_checks_func.test:
Update error number, truncate is no longer invoked if
table is parent in a FK relationship.
mysql-test/t/mdl_sync.test:
Modify test case to reflect and ensure that truncate takes
a exclusive metadata lock.
mysql-test/t/trigger-trans.test:
Update error number, truncate is no longer invoked if
table is parent in a FK relationship.
sql/ha_partition.cc:
Reorganize the various truncate methods. delete_all_rows is now
passed directly to the underlying engines, so as truncate. The
code responsible for truncating individual partitions is moved
to ha_partition::truncate_partition, which is invoked when a
ALTER TABLE t1 TRUNCATE PARTITION p statement is executed.
Since the partition truncate no longer can be invoked via
delete, the bitmap operations are not necessary anymore. The
explicit reset of the auto-increment value is also removed
as the underlying engines are now responsible for reseting
the value.
sql/handler.cc:
Wire up the handler truncate method.
sql/handler.h:
Introduce and document the truncate handler method. It assumes
certain use cases of delete_all_rows.
Add method to retrieve the list of foreign keys referencing a
table. Method is used to avoid truncating tables that are
parent in a foreign key relationship.
sql/share/errmsg-utf8.txt:
Add error message for truncate and FK.
sql/sql_lex.h:
Introduce a flag so that the partition engine can detect when
a partition is being truncated. Used to give a special error.
sql/sql_parse.cc:
Function mysql_truncate_table no longer exists.
sql/sql_partition_admin.cc:
Implement the TRUNCATE PARTITION statement.
sql/sql_truncate.cc:
Change the truncate table implementation to use the new truncate
handler method and to not rely on row-by-row delete anymore.
The truncate handler method is always invoked with a exclusive
metadata lock. Also, it is no longer possible to truncate a
table that is parent in some non-self-referencing foreign key.
storage/archive/ha_archive.cc:
Rename method as the description indicates that in the future
this could be a truncate operation.
storage/blackhole/ha_blackhole.cc:
Implement truncate as no operation for the blackhole engine in
order to remain compatible with older releases.
storage/federated/ha_federated.cc:
Introduce truncate method that invokes delete_all_rows.
This is required to support partition truncate as this
form of truncate does not implement the drop and recreate
protocol.
storage/heap/ha_heap.cc:
Introduce truncate method that invokes delete_all_rows.
This is required to support partition truncate as this
form of truncate does not implement the drop and recreate
protocol.
storage/ibmdb2i/ha_ibmdb2i.cc:
Introduce truncate method that invokes delete_all_rows.
This is required to support partition truncate as this
form of truncate does not implement the drop and recreate
protocol.
storage/innobase/handler/ha_innodb.cc:
Rename delete_all_rows to truncate. InnoDB now does truncate
under a exclusive metadata lock.
Introduce and reorganize methods used to retrieve the list
of foreign keys referenced by a or referencing a table.
storage/myisammrg/ha_myisammrg.cc:
Introduce truncate method that invokes delete_all_rows.
This is required in order to remain compatible with earlier
releases where truncate would resort to a row-by-row delete.
After the patch for Bug#54579, multi inserts done with INSERT DELAYED
are binlogged as normal INSERT. During processing of the statement,
a new query string without the DELAYED keyword is made. The problem
was that this new string was incorrectly made when the INSERT DELAYED
was part of a prepared statement - data was read outside the allocated
buffer.
The reason for this bug was that a pointer to the position of the
DELAYED keyword inside the query string was stored when parsing the
statement. This pointer was then later (at runtime) used (via pointer
subtraction) to find the number of characters to skip when making a
new query string without DELAYED. But when the statement was re-executed
as part of a prepared statement, the original pointer would be invalid
and the pointer subtraction would give a wrong/random result.
This patch fixes the problem by instead storing the offsets from the
beginning of the query string to the start and end of the DELAYED
keyword. These values will not depend on the memory position
of the query string at runtime and therefore not give wrong results
when the statement is executed in a prepared statement.
This bug was a regression introduced by the patch for Bug#54579.
No test case added as this bug is already covered by the existing
binlog.binlog_unsafe test case when running with valgrind.
but broken.
Before this patch, it was allowed to use stored functions in
HANDLER ... READ statements. The problem was that this functionality
was not really supported by the code. Proper locking would for example
not be performed, and it was also possible to break replication by
having stored functions that performed updates.
This patch disallows the use of stored functions in HANDLER ... READ.
Any such statement will now give an ER_NOT_SUPPORTED_YET error.
This is an incompatible change and should be reflected in the
documentation.
Test case added to handler_myisam/handler_innodb.test.
table causes assert failure".
Attempting to use FLUSH TABLE table_list WITH READ LOCK
statement for a MERGE table led to an assertion failure if
one of its children was not present in the list of tables
to be flushed. The problem was not visible in non-debug builds.
The assertion failure was caused by the fact that in such
situations FLUSH TABLES table_list WITH READ LOCK implementation
tried to use (e.g. lock) such child tables without acquiring
metadata lock on them. This happened because when opening tables
we assumed metadata locks on all tables were already acquired
earlier during statement execution and a such assumption was
false for MERGE children.
This patch fixes the problem by ensuring at open_tables() time
that we try to acquire metadata locks on all tables to be opened.
For normal tables such requests are satisfied instantly since
locks are already acquired for them. For MERGE children metadata
locks are acquired in normal fashion.
Note that FLUSH TABLES merge_table WITH READ LOCK will lock for
read both the MERGE table and its children but will flush only
the MERGE table. To flush children one has to mention them in table
list explicitly. This is expected behavior and it is consistent with
usage patterns for this statement (e.g. in mysqlhotcopy script).
mysql-test/r/flush.result:
Added test case for bug #55273 "FLUSH TABLE tm WITH READ LOCK
for Merge table causes assert failure".
mysql-test/t/flush.test:
Added test case for bug #55273 "FLUSH TABLE tm WITH READ LOCK
for Merge table causes assert failure".
sql/sql_base.cc:
Changed lock_table_names() to support newly introduced
MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK flag.
sql/sql_base.h:
Introduced MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK flag for
open_tables() and lock_table_names() which allows to skip
acquiring of global and schema-scope locks when SNW, SNRW or
X metadata locks are acquired.
sql/sql_reload.cc:
Changed "FLUSH TABLES table_list WITH READ LOCK" code not to
cause assert about missing metadata locks when MERGE table is
flushed without one of its underlying tables.
To achieve this we no longer call open_and_lock_tables() with
MYSQL_OPEN_HAS_MDL_LOCK flag so this function automatically
acquires metadata locks on MERGE children if such lock has
not been already acquired at earlier stage. Instead we call
this function with MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK flag to
suppress acquiring of global IX lock in order to keep FLUSH
TABLES table_list WITH READ LOCK compatible with FLUSH TABLE
WITH READ LOCK.
Also changed implementation to use lock_table_names() function
for pre-acquiring of metadata locks instead of custom code.
To implement this change moved setting of open_type member for
table list elements to parser.
sql/sql_yacc.yy:
Now we set acceptable type of table for FLUSH TABLES table_list
WITH READ LOCK at parsing time instead of execution time.
"Access compatibility" syntax
The "wild" "DELETE FROM table_name.* ... USING ..." syntax
for multi-table DELETE statements is documented but it was
lost in the fix for the bug 30234.
The table_ident_opt_wild parser rule has been added
to restore the lost syntax.
mysql-test/r/delete.result:
Test case for bug #53034.
mysql-test/t/delete.test:
Test case for bug #53034.
sql/sql_yacc.yy:
Bug #53034: Multiple-table DELETE statements not accepting
"Access compatibility" syntax
The table_ident_opt_wild parser rule has been added
to restore the lost syntax.
Note: simple extending of table_ident with opt_wild in
the table_alias_ref rule is not acceptable, because
a) it adds one conflict more and b) this conflict resolves
in the inappropriate way.
It was hard to understand what the error really meant.
The error checking in partitioning is done in several different
parts during the execution of a query which can make it
hard to return useful errors.
Added a new error for bad VALUES part in the per PARTITION clause.
Using the more verbose error that a column is not allowed in
the partitioning function instead of just that the function is
not allowed.
mysql-test/r/partition.result:
changed error to be more specific
mysql-test/r/partition_error.result:
updated result
mysql-test/std_data/parts/t1TIMESTAMP.frm:
.frm file of CREATE TABLE t1 (a TIMESTAMP) PARTITION BY HASH(TO_DAYS(a));
mysql-test/t/partition.test:
changed error to be more specific
mysql-test/t/partition_error.test:
Added test (also for verifying behaviour of previously
created tables which is no longer allowed).
Updated expected errors in other places
sql/partition_info.cc:
Added function report_part_expr_error to
be able to return a more specific error.
Renamed fix_func_partition to fix_partition_values
since the function really fixes/checks the VALUES clause.
sql/partition_info.h:
removed part_result_type, since it was unused.
renamed fix_funk_partition->fix_partition_values
added report_part_expr_error
sql/share/errmsg-utf8.txt:
Added a more specific error.
sql/sql_partition.cc:
made use of report_part_expr_error to get a more specific error.
sql/sql_yacc.yy:
Changed error message to be more specific. And return an other error code.