diff options
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 55d4ab0c20f..3a51b5c5610 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4418,7 +4418,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 @@ -4427,19 +4428,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; @@ -4735,7 +4749,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; } @@ -5389,6 +5403,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) { |