IN QUERY CACHE CODE
DESCRIPTION:
MySQL Server crashes sporadically when Query Caching is on and
the server has high contention among clients.
ANALYSIS :
Scenario 1:
In Query_cache::move_by_type() when handling RESULT or its related blocks,
Write Lock is acquired on its parent Query block. However the next and prev
pointers are cached in local variables before lock acquisition. In an extremely
high contention scenario there exists a possibility that
Query_cache::append_result_data() is operating on the same query block
and as a consequence might append a new Result block to the end of Result
blocks Linked List of the Query. This would manipulate the next, prev pointers
of the Block being processed in move_by_type(), however the local pointers
still point to previous nodes there by causing Data Corruption leading to crash.
FIX :
Scenario 1:
The next, prev pointers are now accessed only after Lock acquisition in
Query_cache::move_by_type().
ROBUST AGAINST BUGS IN CALLERS".
Both MDL subsystems and Table Definition Cache code assume
that callers ensure that names of objects passed to them are
not longer than NAME_LEN bytes. Unfortunately due to bugs in
callers this assumption might be broken in some cases. As
result we get nasty bugs causing buffer overruns when we
construct MDL key or TDC key from object names.
This patch makes TDC code more robust against such bugs by
ensuring that we always checking size of result buffer when
constructing TDC keys. This doesn't free its callers from
ensuring that both db and table names are shorter than
NAME_LEN bytes. But at least this steps prevents buffer
overruns in case of bug in caller, replacing them with less
harmful behavior.
This is 5.1-only version of patch.
This patch introduces new version of create_table_def_key()
helper function which constructs TDC key without risk of
result buffer overrun. Places in code that construct TDC keys
were changed to use this function.
Also changed rm_temporary_table() and open_new_frm() functions
to avoid use of "unsafe" strmov() and strxmov() functions and
use safer strnxmov() instead.
ROBUST AGAINST BUGS IN CALLERS".
Both MDL subsystems and Table Definition Cache code assume
that callers ensure that names of objects passed to them are
not longer than NAME_LEN bytes. Unfortunately due to bugs in
callers this assumption might be broken in some cases. As
result we get nasty bugs causing buffer overruns when we
construct MDL key or TDC key from object names.
This patch makes MDL and TDC code more robust against such
bugs by ensuring that we always checking size of result
buffer when constructing MDL and TDC keys. This doesn't
free its callers from ensuring that both db and table names
are shorter than NAME_LEN bytes. But at least these steps
prevents buffer overruns in case of bug in caller, replacing
them with less harmful behavior.
This is 5.5-only version of patch.
Changed code of MDL_key::mdl_key_init() to take into account
size of buffer for the key.
Introduced new version of create_table_def_key() helper function
which constructs TDC key without risk of result buffer overrun.
Places in code that construct TDC keys were changed to use this
function.
Also changed rm_temporary_table() and open_new_frm() functions
to avoid use of "unsafe" strmov() and strxmov() functions and
use safer strnxmov() instead.
and small collateral changes
mysql-test/lib/My/Test.pm:
somehow with "print" we get truncated writes sometimes
mysql-test/suite/perfschema/r/digest_table_full.result:
md5 hashes of statement digests differ, because yacc token codes are different in mariadb
mysql-test/suite/perfschema/r/dml_handler.result:
host table is not ported over yet
mysql-test/suite/perfschema/r/information_schema.result:
host table is not ported over yet
mysql-test/suite/perfschema/r/nesting.result:
this differs, because we don't rewrite general log queries, and multi-statement
packets are logged as a one entry. this result file is identical to what mysql-5.6.5
produces with the --log-raw option.
mysql-test/suite/perfschema/r/relaylog.result:
MariaDB modifies the binlog index file directly, while MySQL 5.6 has a feature "crash-safe binlog index" and modifies a special "crash-safe" shadow copy of the index file and then moves it over. That's why this test shows "NONE" index file writes in MySQL and "MANY" in MariaDB.
mysql-test/suite/perfschema/r/server_init.result:
MariaDB initializes the "manager" resources from the "manager" thread, and starts this thread only when --flush-time is not 0. MySQL 5.6 initializes "manager" resources unconditionally on server startup.
mysql-test/suite/perfschema/r/stage_mdl_global.result:
this differs, because MariaDB disables query cache when query_cache_size=0. MySQL does not
do that, and this causes useless mutex locks and waits.
mysql-test/suite/perfschema/r/statement_digest.result:
md5 hashes of statement digests differ, because yacc token codes are different in mariadb
mysql-test/suite/perfschema/r/statement_digest_consumers.result:
md5 hashes of statement digests differ, because yacc token codes are different in mariadb
mysql-test/suite/perfschema/r/statement_digest_long_query.result:
md5 hashes of statement digests differ, because yacc token codes are different in mariadb
mysql-test/suite/rpl/r/rpl_mixed_drop_create_temp_table.result:
will be updated to match 5.6 when alfranio.correia@oracle.com-20110512172919-c1b5kmum4h52g0ni and anders.song@greatopensource.com-20110105052107-zoab0bsf5a6xxk2y are merged
mysql-test/suite/rpl/r/rpl_non_direct_mixed_mixing_engines.result:
will be updated to match 5.6 when anders.song@greatopensource.com-20110105052107-zoab0bsf5a6xxk2y is merged
The crash happend when combining query cache, prepared statements and using a read only cursor.
sql/sql_cache.cc:
Fixed unlikely error when one adjust query cache size in middle of operation
sql/sql_cursor.cc:
Disable query cache when using cursors. This fixed lp:1039277
tests/mysql_client_test.c:
Test case for lp:1039277
Now partition engine adds underlying tables to the QC and ask underlying tables engine permittion to cache the query and return result of the query.
Incorrect QC cleanup in case of table registration failure fixe.
Unified interface for myisammrg & partitioned engnes for QC.
mysql-test/suite/innodb/t/group_commit_crash.test:
remove autoincrement to avoid rbr being used for insert ... select
mysql-test/suite/innodb/t/group_commit_crash_no_optimize_thread.test:
remove autoincrement to avoid rbr being used for insert ... select
mysys/my_addr_resolve.c:
a pointer to a buffer is returned to the caller -> the buffer cannot be on the stack
mysys/stacktrace.c:
my_vsnprintf() is ok here, in 5.5
sql/share/errmsg-utf8.txt:
correct the error message, as query_cache_type variable is not read-ony anymore
sql/sql_cache.cc:
the caller should verify that query cache resize
is possible, before trying it
sql/sys_vars.cc:
* test if qc resize is possible in the sysvar on_check() funntion,
not in the on_update() function.
* use the error message that better describes the problem
- Changed storage to be 2 bytes instead of sizeof(size_t) (simple optimization)
- Fixed bug when using query_cache_strip_comments and query that started with '('
- Fixed DBUG_PRINT() that used wrong (not initialized) variables.
mysql-test/mysql-test-run.pl:
Added some space to make output more readable.
mysql-test/r/query_cache.result:
Updated test results
mysql-test/t/query_cache.test:
Added test with query_cache_strip_comments
sql/mysql_priv.h:
Added QUERY_CACHE_DB_LENGTH_SIZE
sql/sql_cache.cc:
Fixed bug when using query_cache_strip_comments and query that started with '('
Store db length in 2 characters instead of size_t.
Get db length from correct position (earlier we had an error when query started with ' ')
Fixed DBUG_PRINT() that used wrong (not initialized) variables.
* rename all debugging related command-line options
and variables to start from "debug-", and made them all
OFF by default.
* replace "MySQL" with "MariaDB" in error messages
* "Cast ... converted ... integer to it's ... complement"
is now a note, not a warning
* @@query_cache_strip_comments now has a session scope,
not global.
sql/sql_insert.cc:
CREATE ... IF NOT EXISTS may do nothing, but
it is still not a failure. don't forget to my_ok it.
******
CREATE ... IF NOT EXISTS may do nothing, but
it is still not a failure. don't forget to my_ok it.
sql/sql_table.cc:
small cleanup
******
small cleanup
A buffer large enough to hold the query _plus_ some additional
data is allocated before parsing is started. The additional data
is used by the query cache, and consists of the name of the current
database and a set of flags.
When a packet containing multiple SQL statements is sent to the
server and one of the statements changes the current database
(a "USE <db>" statement), and the name of the new current database
is longer than of the previous, there is not enough space in the
buffer for the new name, and we write out over the buffer boundary.
The fix adds an extra field to store the number of bytes
allocated to the database name in the buffer. If the current
database name changes, and the new name is longer than the
previous one, we refuse to cache the query.
- If USER is given, all threads for that user is signaled
- If SOFT is used then the KILL will not be sent to the handler. This can be used to not interrupt critical things in the handler like 'REPAIR'.
Internally added more kill signals. This gives us more information of why a query/connection was killed.
- KILL_SERVER is used when server is going down. In this case the users gets ER_SHUTDOWN as the reason connection was killed.
- Changed signals to number in correct order, which makes it easier to test how the signal should affect the code.
- New error message ER_CONNECTION_KILLED if connection was killed by 'KILL CONNECTION'. Before we got error ER_SHUTDOWN.
Changed names of not used parameters KILL_QUERY & KILL_CONNCTION to mysql_kill() to not conflict with defines in the server
include/mysql.h.pp:
Updated file
include/mysql_com.h:
Changed names of not used parameters KILL_QUERY & KILL_CONNCTION to mysql_kill() to not conflict with defines in the server
mysql-test/r/kill.result:
Added test of KILL USER
mysql-test/suite/rpl/r/rpl_stm_000001.result:
Updated error code
mysql-test/suite/rpl/t/rpl_stm_000001.test:
Updated error codes
mysql-test/t/flush_read_lock_kill.test:
Updated error codes
mysql-test/t/kill.test:
Added test of KILL USER
plugin/handler_socket/handlersocket/database.cpp:
Removed THD:: from KILL
sql/debug_sync.cc:
Removed THD:: from KILL
sql/event_scheduler.cc:
Removed THD:: from KILL
sql/filesort.cc:
Removed THD:: from KILL
sql/ha_ndbcluster_binlog.cc:
Removed THD:: from KILL
sql/handler.cc:
Removed THD:: from KILL
Simplify code.
sql/lex.h:
Added new keywords HARD | SOFT
sql/log.cc:
Removed THD:: from KILL
Added testing of new error ER_CONNECTION_KILLED
sql/log_event.cc:
Removed THD:: from KILL
Added testing of new error ER_CONNECTION_KILLED
sql/mysql_priv.h:
Added new prototypes
sql/mysqld.cc:
Removed THD:: from KILL
Use KILL_SERVER_HARD signal on shutdown.
sql/scheduler.cc:
Removed THD:: from KILL
Simplify test if connection should be killed
sql/share/errmsg.txt:
New error message ER_CONNECTION_KILLED
sql/slave.cc:
Removed THD:: from KILL
sql/sp_head.cc:
Removed THD:: from KILL
sql/sql_base.cc:
Removed THD:: from KILL
sql/sql_cache.cc:
Removed THD:: from KILL
sql/sql_class.cc:
Removed THD:: from KILL
Added killed_errno()
Only signal kill to storage engine if HARD bit is set.
sql/sql_class.h:
Move KILL options out from THD to make them easier to use in sql_yacc.yy
sql/sql_connect.cc:
Removed THD:: from KILL
sql/sql_delete.cc:
Removed THD:: from KILL
sql/sql_error.cc:
Removed THD:: from KILL
sql/sql_insert.cc:
Removed THD:: from KILL
Simplifed testing if thread is killed.
sql/sql_lex.h:
Added kill options to st_lex
sql/sql_load.cc:
Removed THD:: from KILL
sql/sql_parse.cc:
Added kill options to st_lex
Simplifed and optimzed testing of thd->killed at end of query
Added support for KILL USER
Extended sql_kill() to allow use of more kill signals.
sql/sql_repl.cc:
Removed THD:: from KILL
sql/sql_show.cc:
Removed THD:: from KILL
Simplied testing if query/connection was killed
sql/sql_table.cc:
Removed THD:: from KILL
sql/sql_update.cc:
Removed THD:: from KILL
sql/sql_yacc.yy:
Added support for new KILL syntax: KILL [HARD|SOFT] [CONNECTION|QUERY] [ID | USER user_name]
storage/archive/ha_archive.cc:
Simplify compilation
storage/maria/ha_maria.cc:
Removed THD:: from KILL
Fixed crash when setting query_cache_type to 0.
client/Makefile.am:
Added zlib include (needed by checksum.c)
sql/set_var.cc:
Updated call to disable_query_cache()
sql/sql_cache.cc:
Don't give warning if we start mysqld with --query_cache_type=0 --query_cache-size=0
Fixed crash when setting query_cache_type to 0 (we shouldn't call query_cache.disable_query_cache() when there is no current_thd)
sql/sql_cache.h:
Added THD to disable_query_cache()
client/mysqltest.cc:
Column names.
mysql-test/r/grant_cache_no_prot.result:
fix of text.
mysql-test/r/grant_cache_ps_prot.result:
Fix of test.
mysql-test/r/query_cache.result:
Switching on and off query cache.
mysql-test/t/query_cache.test:
Switching on and off query cache.
mysys/charset.c:
Fix of parser.
sql/handler.cc:
thd added to parameters.
sql/log_event.cc:
thd added to parameters.
sql/log_event_old.cc:
thd added to parameters.
sql/mysql_priv.h:
Fixed functions definitions.
sql/mysqld.cc:
Comments stripping.
sql/set_var.cc:
Switching on and off query cache.
sql/set_var.h:
Switching on and off query cache.
sql/share/errmsg.txt:
New errors.
sql/sql_cache.cc:
Switching query cache on and off, removing comments.
sql/sql_cache.h:
thd added to parameters.
sql/sql_class.h:
Comments stripping.
sql/sql_db.cc:
thd added to parameters.
sql/sql_lex.cc:
lex fixed.
sql/sql_parse.cc:
thd added to parameters.
Resolved all conflicts, bad merges and fixed a few minor bugs in the code.
Commented out the queries from multi_update, view, subselect_sj, func_str,
derived_view, view_grant that failed either with crashes in ps-protocol or
with wrong results.
The failures are clear indications of some bugs in the code and these bugs
are to be fixed.