tables".
Attempting to issue an INSERT DELAYED statement for a MERGE
table might have caused a deadlock if it happened as part of
a transaction or under LOCK TABLES, and there was a concurrent
DDL or LOCK TABLES ... WRITE statement which tried to lock one
of its underlying tables.
The problem occurred when a delayed insert handler thread tried
to open a MERGE table and discovered that to do this it had also
to open all underlying tables and hence acquire metadata
locks on them. Since metadata locks on the underlying tables were
not pre-acquired by the connection thread executing INSERT DELAYED,
attempts to do so might lead to waiting. In this case the
connection thread had to wait for the delayed insert thread.
If the thread which was preventing the lock on the underlying table
from being acquired had to wait for the connection thread (due to
this or other metadata locks), a deadlock occurred.
This deadlock was not detected by the MDL deadlock detector since
waiting for the handler thread by the connection thread is not
represented in the wait-for graph.
This patch solves the problem by ensuring that the delayed
insert handler thread never tries to open underlying tables
of a MERGE table. Instead open_tables() is aborted right after
the parent table is opened and a ER_DELAYED_NOT_SUPPORTED
error is emitted (which is passed to the connection thread and
ultimately to the user).
mysql-test/r/merge.result:
Added test for bug #56251 "Deadlock with INSERT DELAYED and
MERGE tables".
mysql-test/t/merge.test:
Added test for bug #56251 "Deadlock with INSERT DELAYED and
MERGE tables".
sql/sql_base.cc:
Changed open_n_lock_single_table() to take prelocking strategy
as an argument instead of always using DML_prelocking_strategy.
sql/sql_base.h:
Changed open_n_lock_single_table() to take prelocking strategy
as an argument instead of always using DML_prelocking_strategy.
Added a version of this function which is compatible with old
signature.
sql/sql_insert.cc:
When opening MERGE table in delayed insert thread stop and emit
ER_DELAYED_NOT_SUPPORTED right after opening main table and
before opening underlying tables. This ensures that we won't
try to acquire metadata lock on underlying tables which might
lead to a deadlock.
This is achieved by using special prelocking strategy which
abort open_tables() process as soon as we discover that we
have opened table with engine which doesn't support delayed
inserts.
The problem was that issuing XA END when the XA transaction was
already ended, caused an assertion. This assertion tests that
the server does not try to send OK to the client if there has
already been an error reported. The bug was only noticeable on
debug versions of the server.
The reason for the problem was that the trans_xa_end() function
reported success if the transaction was at XA_IDLE state at the
end regardless of any errors occured during processing of
trans_xa_end(). So if the transaction state was XA_IDLE already,
reported errors would be ignored.
This patch fixes the problem by having trans_xa_end() take into
consideration any reported errors. The patch also fixes a similar
bug with XA PREPARE.
Test case added to xa.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.
The Item_func_str_to_date class wasn't providing correct integer DATETIME
representation as expected. This led to wrong comparison result and didn't
allowed the STR_TO_DATE function to be used with indexes.
Also, STR_TO_DATE function was inconsisted on throwing warnings/errors.
Fixed now.
val_int and result_as_longlong methods were added to the Item_func_str_to_date
class.
mysql-test/r/func_time.result:
Test case result adjusted after fixing bug#56271.
mysql-test/r/parser.result:
Test case result adjusted after fixing bug#56271.
mysql-test/r/select.result:
A test case result adjusted after fixing bug#56271.
mysql-test/r/strict.result:
Test case result adjusted after fixing bug#56271.
mysql-test/r/type_datetime.result:
Added a test case for the bug#56271.
mysql-test/t/strict.test:
Test case adjusted after fixing bug#56271.
mysql-test/t/type_datetime.test:
Added a test case for the bug#56271.
sql/item_timefunc.cc:
Bug#56271: Wrong comparison result with STR_TO_DATE function
val_int and result_as_longlong methods were added to the Item_func_str_to_date
class.
Item_func_str_to_date::get_date now throws the ER_WRONG_VALUE_FOR_TYPE warning
on incorrect value.
sql/item_timefunc.h:
Bug#56271: Wrong comparison result with STR_TO_DATE function
val_int and result_as_longlong methods were added to the Item_func_str_to_date
class.
create data dir correctly in initial_database target on Windows
handle case where INSTALL_MYSQLTESTDIR is empty (e.g someone does not want
to install tests)
thread-specific variables weren't set when we load error message files.
per-file comments:
libmysqld/lib_sql.cc
Bug#53251 mysql_library_init fails on second execution with embedded library
we need to call my_thread_init() once more. Normally it's called at the my_init()
stage but that doesn't happen on the second my_init() call.
sql/derror.cc
Bug#53251 mysql_library_init fails on second execution with embedded library
use default errors for the embedded server.
sql/mysqld.cc
Bug#53251 mysql_library_init fails on second execution with embedded library
unregister server errors in clean_up(). Without it the error list contains
that on the second mysql_server_init() which is not good.
sql/set_var.cc
Bug#53251 mysql_library_init fails on second execution with embedded library
sys_var::cleanup() call instead of the destructor
sql/set_var.h
Bug#53251 mysql_library_init fails on second execution with embedded library
sys_var::cleanup() introduced instead of the destructor
sql/sys_vars.h
Bug#53251 mysql_library_init fails on second execution with embedded library
Sys_var_charptr::cleanup() implemented
to allow temp table operations) -- prerequisite patch #3.
Rename open_temporary_table() to open_table_uncached().
open_temporary_table() will be introduced in following patches
to open temporary tables for a statement.
check_merge_table_access() used to do two things:
- set proper database for every merge table child;
- check SELECT | UPDATE | DELETE for merge table children.
Setting database is not needed anymore, since it's done
on the parsing stage.
Thus, check_merge_table_access() can be removed;
needed privileges can be checked using check_table_access().
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.
from 5.1.50 to 5.5.6".
Debug builds of the server aborted due to an assertion
failure when DROP DATABASE statement was run on an
installation which had outdated or corrupt mysql.proc table.
Particularly this affected the mysql_upgrade tool which is
run as part of 5.1 to 5.5 upgrade.
The problem was that sp_drop_db_routines(), which was invoked
during dropping of the database, could have returned without
closing and unlocking mysql.proc table in cases when this
table was not up-to-date with the current server. As a result
further attempt to open and lock the mysql.event table, which
was necessary to complete dropping of the database, ended up
with an assert.
This patch solves this problem by ensuring that
sp_drop_db_routines() always closes mysql.proc table and
releases metadata locks on it. This is achieved by changing
open_proc_table_for_update() function to close tables and
release metadata locks acquired by it in case of failure.
This step also makes behavior of the latter function
consistent with behavior of open_proc_table_for_read()/
open_and_lock_tables().
Test case for this bug was added to sp-destruct.test.
"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.
The lock_type is upgrade to TL_WRITE from TL_WRITE_DELAYED for
INSERT DELAYED when inserting multi values in one statement.
It's safe. But it causes an unsafe warning in SBR.
Make INSERT DELAYED safe by logging it as INSERT without DELAYED.
mysql-test/extra/binlog_tests/binlog_insert_delayed.test:
Updated the test file to test multi INSERT DELAYED statement
is no longer causes an unsafe warning and binlogged as INSERT
without DELAYED.
mysql-test/extra/rpl_tests/create_recursive_construct.inc:
Updated for the patch of bug#54579.
mysql-test/suite/binlog/r/binlog_row_binlog.result:
Updated for the patch of bug#54579.
mysql-test/suite/binlog/r/binlog_statement_insert_delayed.result:
Test result for BUG#54579.
mysql-test/suite/binlog/r/binlog_stm_binlog.result:
Updated for the patch of bug#54579.
mysql-test/suite/binlog/r/binlog_unsafe.result:
Updated for the patch of bug#54579.
mysql-test/suite/binlog/t/binlog_unsafe.test:
Updated for the patch of bug#54579.
sql/sql_insert.cc:
Added code to genetate a new query string for removing
DELAYED keyword for multi INSERT DEALAYED statement.
sql/sql_yacc.yy:
Added code to record the DELAYED keyword position and remove the setting
of unsafe statement for INSERT DELAYED statement
== MYSQL_TYPE_LONGLONG
A MIN/MAX() function with a subquery as its argument could lead
to a debug assertion on debug builds or wrong data on release
ones.
The problem was a combination of the following factors:
- Item_sum_hybrid::fix_fields() might use the argument
(args[0]) to calculate 'hybrid_field_type' which was later used
to decide how the data should be sent to the client.
- Item_sum::make_field() might use the argument again to
calculate the field's type when sending result set metadata to
the client.
- The argument could be changed in between these two calls via
Item::set_arg() leading to inconsistent metadata being
reported.
Here is what was happening for the bug's test case:
1. Item_sum_hybrid::fix_fields() calculates hybrid_field_type
as MYSQL_TYPE_LONGLONG based on args[0] which is an
Item::SUBSELECT_ITEM at that time.
2. A temporary table is created to execute the
query. create_tmp_field_from_item() creates a Field_long object
according to the subselect's max_length.
3. The subselect item in Item_sum_hybrid is replaced by the
Item_field object referencing the newly created Field_long.
4. Item_sum::make_field() rightfully returns the
MYSQL_TYPE_LONG type when calculating the result set metadata.
5. When sending the actual data, Item::send() relies on the
virtual field_type() function which in our case returns
previously calculated hybrid_field_type == MYSQL_TYPE_LONGLONG.
It looks like the only solution is to never refer to the
argument's metadata after the result metadata has been
calculated in fix_fields(), since the argument itself may be
different by then. In this sense, Item_sum::make_field() should
never be used, because it may rely on the argument's metadata
and is only called after fix_fields(). The "default"
implementation in Item::make_field() should be used instead as
it relies only on field_type(), but not on the argument's type.
Fixed by removing Item_sum::make_field() so that the superclass
implementation Item::make_field() is always used.
mysql-test/r/func_group.result:
Added a test case for bug #54465.
mysql-test/t/func_group.test:
Added a test case for bug #54465.
sql/item_sum.cc:
Removed Item_sum::make_field() so that the superclass
implementation Item::make_field() is always used.
sql/item_sum.h:
Removed Item_sum::make_field() so that the superclass
implementation Item::make_field() is always used.
to allow temp table operations) -- prerequisite patch #1.
Move a piece of code that initialiazes TABLE instance
after it was successfully opened into a separate function.
This function will be reused in the following patches.
This assert could be triggered if ALTER EVENT failed to load the
event after altering it. Failing to load the event could for
example happen because of KILL QUERY.
The assert tested that the result of a failed load_named_event()
was OP_LOAD_ERROR. However since load_named_event() returns bool,
this assert did not make any sense. This patch therefore removes
the assert, fixing the problem. The patch also removes
enum_events_error_code since it was unused.
No test case added. The bug fix is trivial and this bug was
easily detected by RQG tests. Further, adding a MTR test case
for this bug would require adding sync points to make the
test case repeatable.
After fix for bug 39653 the shortest available secondary index was used for
full table scan. Primary clustered key was used only if no secondary index
can be used. However, when chosen secondary index includes all fields of the
table being scanned it's better to use primary index since the amount of
data to scan is the same but the primary index is clustered.
Now the find_shortest_key function takes this into account.
mysql-test/suite/innodb/r/innodb_mysql.result:
Added a test case for the bug#55656.
mysql-test/suite/innodb/t/innodb_mysql.test:
Added a test case for the bug#55656.
sql/sql_select.cc:
Bug #55656: mysqldump can be slower after bug #39653 fix.
The find_shortest_key function now prefers clustered primary key
if found secondary key includes all fields of the table.
Before this fix, the server did not recognize 'short' (as in -a)
options but only 'long' (as in --ansi) options
in the startup command line, due to earlier changes in 5.5
introduced for the performance schema.
The root cause is that handle_options() did not honor the
my_getopt_skip_unknown flag when parsing 'short' options.
The fix changes handle_options(), so that my_getopt_skip_unknown is
honored in all cases.
Note that there are limitations to this,
see the added doxygen documentation in handle_options().
The current usage of handle_options() by the server to
parse early performance schema options fits within the limitations.
This has been enforced by an assert for PARSE_EARLY options, for safety.
Before this fix, the ha_read_last_count status variable was defined and
updated internally, for never exposed as a system variable.
This fix exposes the system variable as "Handler_read_last",
for completness of the Handler_read_* system variables interface.
Adjusted tests results accordingly.
Added open log file with FILE_SHARE_DELETE flag on Windows.
sql/log.cc:
added reopen_fstreams();
modified redirect_std_streams(): call to sequence of freopen()
replaced to reopen_fstreams();
modified flush_error_log(): removed file rename for flushed
error log file.
sql/mysqld.cc:
modified main() and init_server_components(): do open log error file
over call to reopen_fstreams().
Before this fix, some tests failed due to lack of instrumentation slots
in the performance schema, because the default sizing was too low.
Now that more code has been instrumented, the default sizing has to be adjusted
to match the current instrumentation consumption.
This change:
- increases the number of rwlock classes from 20 to 30,
- increases the number of rwlock and mutex instances to 1 million.
Both are to account for the volume of data instrumented
when the innodb storage engine is used (because of the innodb buffer pool).
Adjusted the test output accordingly.
Queries involving predicates of the form "const NOT BETWEEN
not_indexed_column AND indexed_column" could return wrong data
due to incorrect handling by the range optimizer.
For "c NOT BETWEEN f1 AND f2" predicates, get_mm_tree()
produces a disjunction of the SEL_ARG trees for "f1 > c" and
"f2 < c". If one of the trees is empty (i.e. one of the
arguments is not sargable) the resulting tree should be empty
as well, since the whole expression in this case is not
sargable.
The above logic is implemented in get_mm_tree() as follows. The
initial state of the resulting tree is NULL (aka empty). We
then iterate through arguments and compute the corresponding
SEL_ARG tree (either "f1 > c" or "f2 < c"). If the resulting
tree is NULL, it is simply replaced by the generated
tree. Otherwise it is replaced by a disjunction of itself and
the generated tree. The obvious flaw in this implementation is
that if the first argument is not sargable and thus produces a
NULL tree, the resulting tree will simply be replaced by the
tree for the second argument. As a result, "c NOT BETWEEN f1
AND f2" will end up as just "f2 < c".
Fixed by adding a check so that when the first argument
produces an empty tree for the NOT BETWEEN case, the loop is
aborted with an empty tree as a result. The whole idea of using
a loop for 2 arguments does not make much sense, but it was
probably used to avoid code duplication for several BETWEEN
variants.
LOCK TABLE+INSERT DELAYED
The problem was that the server could crash if the insert delayed
handler thread was killed due to a conflicting shared metadata
lock. This could happen because the metadata lock ticket was
added to the handler thread before it was properly initialized.
This patch moves the cloning of the acquired metadata lock ticket
until after the handler thread has been properly initialized.