mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
Merge with MariaDB 5.1.49
Removed references to HA_END_SPACE_KEY (which has been 0 for a long time)
This commit is contained in:
154
sql/sql_base.cc
154
sql/sql_base.cc
@@ -1248,6 +1248,12 @@ void close_thread_tables(THD *thd)
|
||||
table->s->table_name.str, (long) table));
|
||||
#endif
|
||||
|
||||
#if defined(ENABLED_DEBUG_SYNC)
|
||||
/* debug_sync may not be initialized for some slave threads */
|
||||
if (thd->debug_sync_control)
|
||||
DEBUG_SYNC(thd, "before_close_thread_tables");
|
||||
#endif
|
||||
|
||||
/*
|
||||
We are assuming here that thd->derived_tables contains ONLY derived
|
||||
tables for this substatement. i.e. instead of approach which uses
|
||||
@@ -2522,7 +2528,7 @@ bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists)
|
||||
put in the thread-open-list.
|
||||
flags Bitmap of flags to modify how open works:
|
||||
MYSQL_LOCK_IGNORE_FLUSH - Open table even if
|
||||
someone has done a flush or namelock on it.
|
||||
someone has done a flush on it.
|
||||
No version number checking is done.
|
||||
MYSQL_OPEN_TEMPORARY_ONLY - Open only temporary
|
||||
table not the base table or view.
|
||||
@@ -2812,8 +2818,10 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
("Found table '%s.%s' with different refresh version",
|
||||
table_list->db, table_list->table_name));
|
||||
|
||||
if (flags & MYSQL_LOCK_IGNORE_FLUSH)
|
||||
/* Ignore FLUSH, but not name locks! */
|
||||
if (flags & MYSQL_LOCK_IGNORE_FLUSH && !table->open_placeholder)
|
||||
{
|
||||
DBUG_ASSERT(table->db_stat);
|
||||
/* Force close at once after usage */
|
||||
thd->version= table->s->version;
|
||||
continue;
|
||||
@@ -4445,7 +4453,8 @@ bool fix_merge_after_open(TABLE_LIST *old_child_list, TABLE_LIST **old_last,
|
||||
Return a appropriate read lock type given a table object.
|
||||
|
||||
@param thd Thread context
|
||||
@param table TABLE object for table to be locked
|
||||
@param lex LEX for the current statement.
|
||||
@param table_list Table list element for table to be locked.
|
||||
|
||||
@remark Due to a statement-based replication limitation, statements such as
|
||||
INSERT INTO .. SELECT FROM .. and CREATE TABLE .. SELECT FROM need
|
||||
@@ -4454,19 +4463,32 @@ bool fix_merge_after_open(TABLE_LIST *old_child_list, TABLE_LIST **old_last,
|
||||
source table. If such a statement gets applied on the slave before
|
||||
the INSERT .. SELECT statement finishes, data on the master could
|
||||
differ from data on the slave and end-up with a discrepancy between
|
||||
the binary log and table state. Furthermore, this does not apply to
|
||||
I_S and log tables as it's always unsafe to replicate such tables
|
||||
under statement-based replication as the table on the slave might
|
||||
contain other data (ie: general_log is enabled on the slave). The
|
||||
statement will be marked as unsafe for SBR in decide_logging_format().
|
||||
the binary log and table state.
|
||||
This also applies to SELECT/SET/DO statements which use stored
|
||||
functions. Calls to such functions are going to be logged as a
|
||||
whole and thus should be serialized against concurrent changes
|
||||
to tables used by those functions. This can be avoided if functions
|
||||
only read data but doing so requires more complex analysis than it
|
||||
is done now (unfortunately, due to bug #53921 "Wrong locks for
|
||||
SELECTs used stored functions may lead to broken SBR" this rule
|
||||
is not followed in cases when stored function or trigger use
|
||||
simple SELECT and not a subselect in their body).
|
||||
Furthermore, this does not apply to I_S and log tables as it's
|
||||
always unsafe to replicate such tables under statement-based
|
||||
replication as the table on the slave might contain other data
|
||||
(ie: general_log is enabled on the slave). The statement will
|
||||
be marked as unsafe for SBR in decide_logging_format().
|
||||
*/
|
||||
|
||||
thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table)
|
||||
thr_lock_type read_lock_type_for_table(THD *thd, LEX *lex,
|
||||
TABLE_LIST *table_list)
|
||||
{
|
||||
bool log_on= mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG);
|
||||
ulong binlog_format= thd->variables.binlog_format;
|
||||
if ((log_on == FALSE) || (binlog_format == BINLOG_FORMAT_ROW) ||
|
||||
(table->s->table_category == TABLE_CATEGORY_PERFORMANCE))
|
||||
(table_list->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) ||
|
||||
(lex->sql_command == SQLCOM_SELECT &&
|
||||
! table_list->prelocking_placeholder))
|
||||
return TL_READ;
|
||||
else
|
||||
return TL_READ_NO_INSERT;
|
||||
@@ -4483,7 +4505,7 @@ thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table)
|
||||
counter - number of opened tables will be return using this parameter
|
||||
flags - bitmap of flags to modify how the tables will be open:
|
||||
MYSQL_LOCK_IGNORE_FLUSH - open table even if someone has
|
||||
done a flush or namelock on it.
|
||||
done a flush on it.
|
||||
|
||||
NOTE
|
||||
Unless we are already in prelocked mode, this function will also precache
|
||||
@@ -4762,7 +4784,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
|
||||
tables->table->reginfo.lock_type= thd->update_lock_default;
|
||||
else if (tables->lock_type == TL_READ_DEFAULT)
|
||||
tables->table->reginfo.lock_type=
|
||||
read_lock_type_for_table(thd, tables->table);
|
||||
read_lock_type_for_table(thd, thd->lex, tables);
|
||||
else
|
||||
tables->table->reginfo.lock_type= tables->lock_type;
|
||||
}
|
||||
@@ -5082,7 +5104,7 @@ int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived)
|
||||
tables - list of tables for open
|
||||
flags - bitmap of flags to modify how the tables will be open:
|
||||
MYSQL_LOCK_IGNORE_FLUSH - open table even if someone has
|
||||
done a flush or namelock on it.
|
||||
done a flush on it.
|
||||
|
||||
RETURN
|
||||
FALSE - ok
|
||||
@@ -5181,53 +5203,75 @@ int decide_logging_format(THD *thd, TABLE_LIST *tables)
|
||||
set with all the capabilities bits set and one with no
|
||||
capabilities bits set.
|
||||
*/
|
||||
handler::Table_flags flags_some_set= 0;
|
||||
handler::Table_flags flags_all_set=
|
||||
handler::Table_flags flags_write_some_set= 0;
|
||||
handler::Table_flags flags_access_some_set= 0;
|
||||
handler::Table_flags flags_write_all_set=
|
||||
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE;
|
||||
|
||||
my_bool multi_engine= FALSE;
|
||||
void* prev_ht= NULL;
|
||||
/*
|
||||
If different types of engines are about to be updated.
|
||||
For example: Innodb and Falcon; Innodb and MyIsam.
|
||||
*/
|
||||
my_bool multi_write_engine= FALSE;
|
||||
void* prev_write_ht= NULL;
|
||||
|
||||
/*
|
||||
If different types of engines are about to be accessed
|
||||
and any of them is about to be updated. For example:
|
||||
Innodb and Falcon; Innodb and MyIsam.
|
||||
*/
|
||||
my_bool multi_access_engine= FALSE;
|
||||
void* prev_access_ht= NULL;
|
||||
for (TABLE_LIST *table= tables; table; table= table->next_global)
|
||||
{
|
||||
if (table->placeholder())
|
||||
continue;
|
||||
if (table->table->s->table_category == TABLE_CATEGORY_PERFORMANCE)
|
||||
thd->lex->set_stmt_unsafe();
|
||||
ulonglong const flags= table->table->file->ha_table_flags();
|
||||
if (table->lock_type >= TL_WRITE_ALLOW_WRITE)
|
||||
{
|
||||
ulonglong const flags= table->table->file->ha_table_flags();
|
||||
DBUG_PRINT("info", ("table: %s; ha_table_flags: %s%s",
|
||||
table->table_name,
|
||||
FLAGSTR(flags, HA_BINLOG_STMT_CAPABLE),
|
||||
FLAGSTR(flags, HA_BINLOG_ROW_CAPABLE)));
|
||||
if (prev_ht && prev_ht != table->table->file->ht)
|
||||
multi_engine= TRUE;
|
||||
prev_ht= table->table->file->ht;
|
||||
flags_all_set &= flags;
|
||||
flags_some_set |= flags;
|
||||
if (prev_write_ht && prev_write_ht != table->table->file->ht)
|
||||
multi_write_engine= TRUE;
|
||||
prev_write_ht= table->table->file->ht;
|
||||
flags_write_all_set &= flags;
|
||||
flags_write_some_set |= flags;
|
||||
}
|
||||
if (prev_access_ht && prev_access_ht != table->table->file->ht)
|
||||
multi_access_engine= TRUE;
|
||||
prev_access_ht= table->table->file->ht;
|
||||
flags_access_some_set |= flags;
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("flags_all_set: %s%s",
|
||||
FLAGSTR(flags_all_set, HA_BINLOG_STMT_CAPABLE),
|
||||
FLAGSTR(flags_all_set, HA_BINLOG_ROW_CAPABLE)));
|
||||
DBUG_PRINT("info", ("flags_some_set: %s%s",
|
||||
FLAGSTR(flags_some_set, HA_BINLOG_STMT_CAPABLE),
|
||||
FLAGSTR(flags_some_set, HA_BINLOG_ROW_CAPABLE)));
|
||||
DBUG_PRINT("info", ("flags_write_all_set: %s%s",
|
||||
FLAGSTR(flags_write_all_set, HA_BINLOG_STMT_CAPABLE),
|
||||
FLAGSTR(flags_write_all_set, HA_BINLOG_ROW_CAPABLE)));
|
||||
DBUG_PRINT("info", ("flags_write_some_set: %s%s",
|
||||
FLAGSTR(flags_write_some_set, HA_BINLOG_STMT_CAPABLE),
|
||||
FLAGSTR(flags_write_some_set, HA_BINLOG_ROW_CAPABLE)));
|
||||
DBUG_PRINT("info", ("flags_access_some_set: %s%s",
|
||||
FLAGSTR(flags_access_some_set, HA_BINLOG_STMT_CAPABLE),
|
||||
FLAGSTR(flags_access_some_set, HA_BINLOG_ROW_CAPABLE)));
|
||||
DBUG_PRINT("info", ("multi_write_engine: %s",
|
||||
multi_write_engine ? "TRUE" : "FALSE"));
|
||||
DBUG_PRINT("info", ("multi_access_engine: %s",
|
||||
multi_access_engine ? "TRUE" : "FALSE"));
|
||||
DBUG_PRINT("info", ("thd->variables.binlog_format: %ld",
|
||||
thd->variables.binlog_format));
|
||||
DBUG_PRINT("info", ("multi_engine: %s",
|
||||
multi_engine ? "TRUE" : "FALSE"));
|
||||
|
||||
int error= 0;
|
||||
if (flags_all_set == 0)
|
||||
if (flags_write_all_set == 0)
|
||||
{
|
||||
my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0),
|
||||
"Statement cannot be logged to the binary log in"
|
||||
" row-based nor statement-based format");
|
||||
}
|
||||
else if (thd->variables.binlog_format == BINLOG_FORMAT_STMT &&
|
||||
(flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0)
|
||||
(flags_write_all_set & HA_BINLOG_STMT_CAPABLE) == 0)
|
||||
{
|
||||
my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0),
|
||||
"Statement-based format required for this statement,"
|
||||
@@ -5235,7 +5279,7 @@ int decide_logging_format(THD *thd, TABLE_LIST *tables)
|
||||
}
|
||||
else if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW ||
|
||||
thd->lex->is_stmt_unsafe()) &&
|
||||
(flags_all_set & HA_BINLOG_ROW_CAPABLE) == 0)
|
||||
(flags_write_all_set & HA_BINLOG_ROW_CAPABLE) == 0)
|
||||
{
|
||||
my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0),
|
||||
"Row-based format required for this statement,"
|
||||
@@ -5248,8 +5292,8 @@ int decide_logging_format(THD *thd, TABLE_LIST *tables)
|
||||
statement cannot be logged atomically, so we generate an error
|
||||
rather than allowing the binlog to become corrupt.
|
||||
*/
|
||||
if (multi_engine &&
|
||||
(flags_some_set & HA_HAS_OWN_BINLOGGING))
|
||||
if (multi_write_engine &&
|
||||
(flags_write_some_set & HA_HAS_OWN_BINLOGGING))
|
||||
{
|
||||
error= ER_BINLOG_LOGGING_IMPOSSIBLE;
|
||||
my_error(error, MYF(0),
|
||||
@@ -5257,6 +5301,16 @@ int decide_logging_format(THD *thd, TABLE_LIST *tables)
|
||||
" than one engine involved and at least one engine"
|
||||
" is self-logging");
|
||||
}
|
||||
/*
|
||||
Reading from a self-logging engine and updating another engine
|
||||
generates changes that are written to the binary log in the
|
||||
statement format and may make slaves to diverge. In the mixed
|
||||
mode, such changes should be written to the binary log in the
|
||||
row format.
|
||||
*/
|
||||
else if (multi_access_engine &&
|
||||
(flags_access_some_set & HA_HAS_OWN_BINLOGGING))
|
||||
thd->lex->set_stmt_unsafe();
|
||||
|
||||
DBUG_PRINT("info", ("error: %d", error));
|
||||
|
||||
@@ -5276,7 +5330,7 @@ int decide_logging_format(THD *thd, TABLE_LIST *tables)
|
||||
here.
|
||||
*/
|
||||
if (thd->lex->is_stmt_unsafe() ||
|
||||
(flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0)
|
||||
(flags_write_all_set & HA_BINLOG_STMT_CAPABLE) == 0)
|
||||
{
|
||||
thd->set_current_stmt_binlog_row_based_if_mixed();
|
||||
}
|
||||
@@ -5384,6 +5438,8 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
DEBUG_SYNC(thd, "after_lock_tables_takes_lock");
|
||||
|
||||
if (thd->lex->requires_prelocking() &&
|
||||
thd->lex->sql_command != SQLCOM_LOCK_TABLES)
|
||||
{
|
||||
@@ -8889,7 +8945,7 @@ bool is_equal(const LEX_STRING *a, const LEX_STRING *b)
|
||||
|
||||
/*
|
||||
SYNOPSIS
|
||||
abort_and_upgrade_lock()
|
||||
abort_and_upgrade_lock_and_close_table()
|
||||
lpt Parameter passing struct
|
||||
All parameters passed through the ALTER_PARTITION_PARAM_TYPE object
|
||||
RETURN VALUE
|
||||
@@ -8898,7 +8954,7 @@ bool is_equal(const LEX_STRING *a, const LEX_STRING *b)
|
||||
Remember old lock level (for possible downgrade later on), abort all
|
||||
waiting threads and ensure that all keeping locks currently are
|
||||
completed such that we own the lock exclusively and no other interaction
|
||||
is ongoing.
|
||||
is ongoing. Close the table and hold the name lock.
|
||||
|
||||
thd Thread object
|
||||
table Table object
|
||||
@@ -8907,18 +8963,26 @@ bool is_equal(const LEX_STRING *a, const LEX_STRING *b)
|
||||
old_lock_level Old lock level
|
||||
*/
|
||||
|
||||
int abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt)
|
||||
int abort_and_upgrade_lock_and_close_table(ALTER_PARTITION_PARAM_TYPE *lpt)
|
||||
{
|
||||
uint flags= RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG;
|
||||
DBUG_ENTER("abort_and_upgrade_locks");
|
||||
const char *db= lpt->db;
|
||||
const char *table_name= lpt->table_name;
|
||||
THD *thd= lpt->thd;
|
||||
DBUG_ENTER("abort_and_upgrade_lock_and_close_table");
|
||||
|
||||
lpt->old_lock_type= lpt->table->reginfo.lock_type;
|
||||
safe_mutex_assert_not_owner(&LOCK_open);
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
/* If MERGE child, forward lock handling to parent. */
|
||||
mysql_lock_abort(lpt->thd, lpt->table->parent ? lpt->table->parent :
|
||||
lpt->table, TRUE);
|
||||
VOID(remove_table_from_cache(lpt->thd, lpt->db, lpt->table_name, flags,
|
||||
FALSE));
|
||||
mysql_lock_abort(thd, lpt->table->parent ? lpt->table->parent : lpt->table,
|
||||
TRUE);
|
||||
if (remove_table_from_cache(thd, db, table_name, flags, FALSE))
|
||||
{
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
close_data_files_and_morph_locks(thd, db, table_name);
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user