Commit graph

3 commits

Author SHA1 Message Date
Davi Arnaut
2100ec9ec9 Bug#33362: Query cache invalidation (truncate) may hang
if cached query uses many tables

The problem was that query cache would not properly cache
queries which used 256 or more tables but yet would leave
behind query cache blocks pointing to freed (destroyed)
data. Later when invalidating (due to a truncate) query cache
would attempt to grab a lock which resided in the freed data,
leading to hangs or undefined behavior.

This was happening due to a improper return value from the
function responsible for registering the tables used in the
query (so the cache can be invalidated later if one of the
tables is modified). The function expected a return value of
type boolean (char, 8 bits) indicating success (1) or failure
(0) but the number of tables registered (unsigned int, 32 bits)
was being returned instead. This caused the function to return
failure for cases where it had actually succeed because when
a type (unsigned int) is converted to a narrower type (char),
the excess bits on the left are discarded. Thus if the 8
rightmost bits are zero, the return value will be 0 (failure).

The solution is to simply return true (1) only if the number of
registered table is greater than zero and false (0) otherwise.

mysql-test/r/query_cache_merge.result:
  Add test case result for Bug#33362
mysql-test/t/query_cache_merge.test:
  Add test case for Bug#33362
sql/sql_cache.cc:
  Return 1 or 0 depending on the number of registered tables.
2008-06-03 10:59:46 -03:00
unknown
a63dde5a5b Tentative implementation of
WL#4165 Prepared statements: validation 
WL#4166 Prepared statements: automatic re-prepare
Fixes
Bug#27430 Crash in subquery code when in PS and table DDL changed after PREPARE
Bug#27690 Re-execution of prepared statement after table was replaced with a view crashes
Bug#27420 A combination of PS and view operations cause error + assertion on shutdown

The basic idea of the patch is to keep track of table metadata between
prepared statement prepare and execute. If some table used in the statement
has changed, the prepared statement is re-prepared before execution.

See WL#4165 and WL#4166 contents and comments in the code for details
of the implementation.


include/my_global.h:
  Remove 'register' keyword to avoid warnings when swapping large structures
  that don't fit into a register. Any modern compiler is capable of placing
  a variable in a register when that would benefit performance.
mysql-test/r/ps_1general.result:
  Update test results: since now we re-prepare automatically,
  more correct results are produced in prepare-ddl-execute scenario.
mysql-test/r/query_cache_merge.result:
  Ensure that the table definition cache is large enough for
  the test to pass in --ps-protocol
mysql-test/r/trigger.result:
  Update test results to reflect automatic statement reprepare.
mysql-test/t/disabled.def:
  Enable ps_ddl.test, which now passes.
mysql-test/t/ps_1general.test:
  Since now we re-execute prepared statements after DDL successfully,
  change the test to produce repeatable results. Remove expectancy of
  an error in one place where now we automatically reprepare the prepared
  statement.
mysql-test/t/query_cache_merge.test:
  Ensure the table definition cache is large enough for the test to pass
  in --ps-protocol
mysql-test/t/trigger.test:
  Sinc
sql/item.cc:
  Implement Item_param "copy" functionality, used at re-prepare of
  a prepared statement.
  We copy the type of the original parameter, and move the assigned value,
  if any. Sic, the value is "moved", since it can be quite big --
  e.g. in case we deal with a LONG DATA parameter.
  It's essential to move the value from the old parameter since
  at the time of re-prepare the client packet with the necessary information
  may be not available.
sql/item.h:
  Declare a new method used for reprepare.
sql/my_decimal.h:
  Implement "swap()" functionality of class my_decimal to be
  able to easily swap two decimal values.
sql/mysql_priv.h:
  Declare enum_metadata_type.
sql/mysqld.cc:
  Implement a status variable for the number of reprepared statements.
sql/sql_base.cc:
  Implement metadata version validation.
sql/share/errmsg.txt:
  Add two new error messages: ER_NEED_REPREPARE and ER_PS_REBIND.
  The first error (theoretically) never reaches the user.
  It is issued by the metadata validation framework when a metadata version
  has changed between prepare and execute. Later on it's intercepted
  and the statement is automatically re-prepared. Only if the error
  has occurred repeatedly MAX_REPREPARE_ATTEMTS (3) times do we
  return it to the user.
  
  The second error is issued when after re-prepare we discover
  that the metadata we sent over to the client using the binary
  protocol differs drammatically from the new result set metadata 
  that the reprepared statement produces (e.g. number of result
  set columns is different).
sql/sql_class.cc:
  Implement metadata version validation framework.
sql/sql_class.h:
  Declarations for metadata version validation framework.
sql/sql_parse.cc:
  Mark commands for which we must invalidate and reprepare a prepared
  statement when metadata has changed.
sql/sql_prepare.cc:
  Implement WL#4165 and WL#4166 (limited support of metadata validation
  and re-prepare).
sql/table.h:
  Implement metadata validation.
tests/mysql_client_test.c:
  Add a test case for WL#4166
2008-04-08 20:01:20 +04:00
unknown
64393d7e24 Move test that uses many tables (in query_cache.test) to separate test so that we can get it 'skipped' instead of 'failed' on system where we can't open many files.
client/mysqltest.c:
  Fix that LET can be used with queries that return multiple columns
libmysql/errmsg.c:
  Extend socket name to 100 characters in error messages
libmysql/libmysql.c:
  Reset some variables to make ensure that we can call mysql_server_init()/mysql_server_end() many times
mysql-test/mysql-test-run.sh:
  Set open-files-limit to 1024
mysql-test/r/loaddata.result:
  Add test case for LOAD DATA bug report (was not a bug)
mysql-test/r/query_cache.result:
  Move test with many tables to separate test
mysql-test/r/select_safe.result:
  Make test repeatable
mysql-test/t/loaddata.test:
  Add test case for LOAD DATA bug report (was not a bug)
mysql-test/t/query_cache.test:
  Move test with many tables to separate test
mysql-test/t/select_safe.test:
  Make test repeatable
sql/field.cc:
  Portability fix for gcc 3.3
sql/mysqld.cc:
  Store in open_files_limit the true number of files we can open (if system supports it)
sql/sql_load.cc:
  Safety fix
2003-08-22 04:07:40 +03:00