1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Fixed Bug#11756013 (formerly known as bug#47870):

BOGUS "THE TABLE MYSQL.PROC IS MISSING,..."

There was a race condition between loading a stored routine
(function/procedure/trigger) specified by fully qualified name
SCHEMA_NAME.PROC_NAME and dropping the stored routine database.

The problem was that there is a window for race condition when one server
thread tries to load a stored routine being executed and the other thread
tries to drop the stored routine schema.

This condition race window exists in implementation of function
mysql_change_db() called by db_load_routine() during loading of stored
routine to cache. Function mysql_change_db() calls check_db_dir_existence()
that might failed because specified database was dropped during concurrent
execution of DROP SCHEMA statement. db_load_routine() calls mysql_change_db()
with flag 'force_switch' set to 'true' value so when referenced db is not found
then my_error() is not called and function mysql_change_db() returns ok.
This shadows information about schema opening error in db_load_routine().
Then db_load_routine() makes attempt to parse stored routine that is failed.
This makes to return error to sp_cache_routines_and_add_tables_aux() but since
during error generation a call to my_error wasn't made and hence
THD::main_da wasn't set we set the generic "mysql.proc table corrupt" error
when running sp_cache_routines_and_add_tables_aux().

The fix is to install an error handler inside db_load_routine() for
the mysql_op_change_db() call, and check later if the ER_BAD_DB_ERROR
was caught.
This commit is contained in:
Dmitry Shulga
2011-06-23 20:41:04 +07:00
parent b3696af2e6
commit 07056eb984
4 changed files with 87 additions and 3 deletions

View File

@ -26,6 +26,7 @@
#ifdef __WIN__
#include <direct.h>
#endif
#include "debug_sync.h"
#define MAX_DROP_TABLE_Q_LEN 1024
@ -1702,6 +1703,8 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
}
#endif
DEBUG_SYNC(thd, "before_db_dir_check");
if (check_db_dir_existence(new_db_file_name.str))
{
if (force_switch)