mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge tsmith@bk-internal.mysql.com:/home/bk/mysql-5.1-rpl
into maint1.mysql.com:/data/localhome/tsmith/bk/maint/51 include/m_ctype.h: Auto merged mysql-test/Makefile.am: Auto merged mysql-test/lib/mtr_report.pl: Auto merged mysql-test/r/rpl_ssl.result: Auto merged mysql-test/t/innodb.test: Auto merged mysql-test/t/multi_update.test: Auto merged mysql-test/t/rpl_row_until.test: Auto merged mysql-test/t/rpl_ssl.test: Auto merged mysql-test/t/rpl_stm_until.test: Auto merged mysys/charset-def.c: Auto merged mysys/charset.c: Auto merged sql/item_create.cc: Auto merged sql/log_event.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_update.cc: Auto merged strings/ctype-big5.c: Auto merged strings/ctype-gbk.c: Auto merged strings/ctype-sjis.c: Auto merged strings/ctype-uca.c: Auto merged strings/ctype.c: Auto merged BitKeeper/deleted/.del-binlog_innodb.result: Delete: mysql-test/r/binlog_innodb.result BitKeeper/deleted/.del-binlog_innodb.test: Delete: mysql-test/t/binlog_innodb.test mysql-test/r/binlog_innodb.result: Fix merge of two independent binlog_innodb tests (from -rpl and -maint) mysql-test/t/binlog_innodb.test: Fix merge of two independent binlog_innodb tests (from -rpl and -maint) mysql-test/r/innodb.result: Use local (manual merge) mysql-test/r/multi_update.result: Use remote (manual merge) mysql-test/t/rpl_log_pos.test: Manual merge mysql-test/r/rpl_log_pos.result: Manual merge, part 2
This commit is contained in:
130
sql/sql_base.cc
130
sql/sql_base.cc
@ -3955,6 +3955,121 @@ static void mark_real_tables_as_free_for_reuse(TABLE_LIST *table)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Decide on logging format to use for the statement.
|
||||
|
||||
Compute the capabilities vector for the involved storage engines
|
||||
and mask out the flags for the binary log. Right now, the binlog
|
||||
flags only include the capabilities of the storage engines, so this
|
||||
is safe.
|
||||
|
||||
We now have three alternatives that prevent the statement from
|
||||
being loggable:
|
||||
|
||||
1. If there are no capabilities left (all flags are clear) it is
|
||||
not possible to log the statement at all, so we roll back the
|
||||
statement and report an error.
|
||||
|
||||
2. Statement mode is set, but the capabilities indicate that
|
||||
statement format is not possible.
|
||||
|
||||
3. Row mode is set, but the capabilities indicate that row
|
||||
format is not possible.
|
||||
|
||||
4. Statement is unsafe, but the capabilities indicate that row
|
||||
format is not possible.
|
||||
|
||||
If we are in MIXED mode, we then decide what logging format to use:
|
||||
|
||||
1. If the statement is unsafe, row-based logging is used.
|
||||
|
||||
2. If statement-based logging is not possible, row-based logging is
|
||||
used.
|
||||
|
||||
3. Otherwise, statement-based logging is used.
|
||||
|
||||
@param thd Client thread
|
||||
@param tables Tables involved in the query
|
||||
*/
|
||||
|
||||
int decide_logging_format(THD *thd, TABLE_LIST *tables)
|
||||
{
|
||||
if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG))
|
||||
{
|
||||
handler::Table_flags binlog_flags= ~handler::Table_flags();
|
||||
for (TABLE_LIST *table= tables; table; table= table->next_global)
|
||||
if (!table->placeholder() && table->lock_type >= TL_WRITE_ALLOW_WRITE)
|
||||
{
|
||||
#define FLAGSTR(S,F) ((S) & (F) ? #F " " : "")
|
||||
#ifndef DBUG_OFF
|
||||
ulonglong 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)));
|
||||
#endif
|
||||
binlog_flags &= table->table->file->ha_table_flags();
|
||||
}
|
||||
binlog_flags&= HA_BINLOG_FLAGS;
|
||||
DBUG_PRINT("info", ("binlog_flags: %s%s",
|
||||
FLAGSTR(binlog_flags, HA_BINLOG_STMT_CAPABLE),
|
||||
FLAGSTR(binlog_flags, HA_BINLOG_ROW_CAPABLE)));
|
||||
DBUG_PRINT("info", ("thd->variables.binlog_format: %ld",
|
||||
thd->variables.binlog_format));
|
||||
|
||||
int error= 0;
|
||||
if (binlog_flags == 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 &&
|
||||
(binlog_flags & HA_BINLOG_STMT_CAPABLE) == 0)
|
||||
{
|
||||
my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0),
|
||||
"Statement-based format required for this statement,"
|
||||
" but not allowed by this combination of engines");
|
||||
}
|
||||
else if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW ||
|
||||
thd->lex->is_stmt_unsafe()) &&
|
||||
(binlog_flags & HA_BINLOG_ROW_CAPABLE) == 0)
|
||||
{
|
||||
my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0),
|
||||
"Row-based format required for this statement,"
|
||||
" but not allowed by this combination of engines");
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("error: %d", error));
|
||||
|
||||
if (error)
|
||||
{
|
||||
ha_rollback_stmt(thd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
We switch to row-based format if we are in mixed mode and one of
|
||||
the following are true:
|
||||
|
||||
1. If the statement is unsafe
|
||||
2. If statement format cannot be used
|
||||
|
||||
Observe that point to cannot be decided before the tables
|
||||
involved in a statement has been checked, i.e., we cannot put
|
||||
this code in reset_current_stmt_binlog_row_based(), it has to be
|
||||
here.
|
||||
*/
|
||||
if (thd->lex->is_stmt_unsafe() ||
|
||||
(binlog_flags & HA_BINLOG_STMT_CAPABLE) == 0)
|
||||
{
|
||||
thd->set_current_stmt_binlog_row_based_if_mixed();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Lock all tables in list
|
||||
|
||||
@ -3993,17 +4108,10 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
|
||||
in prelocked mode.
|
||||
*/
|
||||
DBUG_ASSERT(!thd->prelocked_mode || !thd->lex->requires_prelocking());
|
||||
|
||||
*need_reopen= FALSE;
|
||||
|
||||
/*
|
||||
CREATE ... SELECT UUID() locks no tables, we have to test here.
|
||||
*/
|
||||
if (thd->lex->binlog_row_based_if_mixed)
|
||||
thd->set_current_stmt_binlog_row_based_if_mixed();
|
||||
|
||||
if (!tables && !thd->lex->requires_prelocking())
|
||||
DBUG_RETURN(0);
|
||||
DBUG_RETURN(decide_logging_format(thd, tables));
|
||||
|
||||
/*
|
||||
We need this extra check for thd->prelocked_mode because we want to avoid
|
||||
@ -4046,7 +4154,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
|
||||
if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED &&
|
||||
has_two_write_locked_tables_with_auto_increment(tables))
|
||||
{
|
||||
thd->lex->binlog_row_based_if_mixed= TRUE;
|
||||
thd->lex->set_stmt_unsafe();
|
||||
thd->set_current_stmt_binlog_row_based_if_mixed();
|
||||
}
|
||||
}
|
||||
@ -4061,6 +4169,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
|
||||
}
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
if (thd->lex->requires_prelocking() &&
|
||||
thd->lex->sql_command != SQLCOM_LOCK_TABLES)
|
||||
{
|
||||
@ -4127,7 +4236,8 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
|
||||
thd->prelocked_mode= PRELOCKED_UNDER_LOCK_TABLES;
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
||||
DBUG_RETURN(decide_logging_format(thd, tables));
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user