1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

Bug #57666 Unclear warning with broken text in error log on INSERT DELAYED

It is not necessary to support INSERT DELAYED for a single value insert,
while we do not support that for multi-values insert when binlog is
enabled in SBR.

The lock_type is upgrade to TL_WRITE from TL_WRITE_DELAYED for
INSERT DELAYED for single value insert as multi-values insert
did when binlog is enabled. Then it's safe. And binlog it as
INSERT without DELAYED.
This commit is contained in:
2010-11-29 11:04:16 +08:00
parent 30376d282d
commit 08db5f7eb6
6 changed files with 31 additions and 77 deletions

View File

@ -420,8 +420,7 @@ void prepare_triggers_for_insert_stmt(TABLE *table)
static
void upgrade_lock_type(THD *thd, thr_lock_type *lock_type,
enum_duplicates duplic,
bool is_multi_insert)
enum_duplicates duplic)
{
if (duplic == DUP_UPDATE ||
(duplic == DUP_REPLACE && *lock_type == TL_WRITE_CONCURRENT_INSERT))
@ -470,10 +469,9 @@ void upgrade_lock_type(THD *thd, thr_lock_type *lock_type,
return;
}
bool log_on= (thd->variables.option_bits & OPTION_BIN_LOG ||
! (thd->security_ctx->master_access & SUPER_ACL));
bool log_on= (thd->variables.option_bits & OPTION_BIN_LOG);
if (global_system_variables.binlog_format == BINLOG_FORMAT_STMT &&
log_on && mysql_bin_log.is_open() && is_multi_insert)
log_on && mysql_bin_log.is_open())
{
/*
Statement-based binary logging does not work in this case, because:
@ -677,8 +675,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
By default, both logs are enabled (this won't cause problems if the server
runs without --log-bin).
*/
bool log_on= ((thd->variables.option_bits & OPTION_BIN_LOG) ||
(!(thd->security_ctx->master_access & SUPER_ACL)));
bool log_on= (thd->variables.option_bits & OPTION_BIN_LOG);
#endif
thr_lock_type lock_type;
Item *unused_conds= 0;
@ -688,8 +685,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
Upgrade lock type if the requested lock is incompatible with
the current connection mode or table operation.
*/
upgrade_lock_type(thd, &table_list->lock_type, duplic,
values_list.elements > 1);
upgrade_lock_type(thd, &table_list->lock_type, duplic);
/*
We can't write-delayed into a table locked with LOCK TABLES:
@ -1022,7 +1018,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
DBUG_ASSERT(thd->killed != THD::KILL_BAD_DATA || error > 0);
if (was_insert_delayed && table_list->lock_type == TL_WRITE)
{
/* Binlog multi INSERT DELAYED as INSERT without DELAYED. */
/* Binlog INSERT DELAYED as INSERT without DELAYED. */
String log_query;
if (create_insert_stmt_from_insert_delayed(thd, &log_query))
{
@ -1905,22 +1901,6 @@ public:
thd.command=COM_DELAYED_INSERT;
thd.lex->current_select= 0; // for my_message_sql
thd.lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock()
/*
Statement-based replication of INSERT DELAYED has problems with
RAND() and user variables, so in mixed mode we go to row-based.
For normal commands, the unsafe flag is set at parse time.
However, since the flag is a member of the THD object, of which
the delayed_insert thread has its own copy, we must set the
statement to unsafe here and explicitly set row logging mode.
@todo set_current_stmt_binlog_format_row_if_mixed should not be
called by anything else than thd->decide_logging_format(). When
we call set_current_blah here, none of the checks in
decide_logging_format is made. We should probably call
thd->decide_logging_format() directly instead. /Sven
*/
thd.lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_DELAYED);
thd.set_current_stmt_binlog_format_row_if_mixed();
/*
Prevent changes to global.lock_wait_timeout from affecting
delayed insert threads as any timeouts in delayed inserts
@ -2650,11 +2630,11 @@ pthread_handler_t handle_delayed_insert(void *arg)
}
thd->lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock()
/*
Statement-based replication of INSERT DELAYED has problems with RAND()
and user vars, so in mixed mode we go to row-based.
INSERT DELAYED has to go to row-based format because the time
at which rows are inserted cannot be determined in mixed mode.
*/
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_DELAYED);
thd->set_current_stmt_binlog_format_row_if_mixed();
/*
@ -2921,6 +2901,13 @@ bool Delayed_insert::handle_inserts(void)
(ulong) row->query.length));
if (log_query)
{
/*
Guaranteed that the INSERT DELAYED STMT will not be here
in SBR when mysql binlog is enabled.
*/
DBUG_ASSERT(!(mysql_bin_log.is_open() &&
!thd.is_current_stmt_binlog_format_row()));
/*
This is the first value of an INSERT statement.
It is the right place to clear a forced insert_id.
@ -2988,39 +2975,6 @@ bool Delayed_insert::handle_inserts(void)
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
}
if (log_query && mysql_bin_log.is_open())
{
bool backup_time_zone_used = thd.time_zone_used;
Time_zone *backup_time_zone = thd.variables.time_zone;
if (row->time_zone != NULL)
{
thd.time_zone_used = true;
thd.variables.time_zone = row->time_zone;
}
/* if the delayed insert was killed, the killed status is
ignored while binlogging */
int errcode= 0;
if (thd.killed == THD::NOT_KILLED)
errcode= query_error_code(&thd, TRUE);
/*
If the query has several rows to insert, only the first row will come
here. In row-based binlogging, this means that the first row will be
written to binlog as one Table_map event and one Rows event (due to an
event flush done in binlog_query()), then all other rows of this query
will be binlogged together as one single Table_map event and one
single Rows event.
*/
if (thd.binlog_query(THD::ROW_QUERY_TYPE,
row->query.str, row->query.length,
FALSE, FALSE, FALSE, errcode))
goto err;
thd.time_zone_used = backup_time_zone_used;
thd.variables.time_zone = backup_time_zone;
}
if (table->s->blob_fields)
free_delayed_insert_blobs(table);
thread_safe_decrement(delayed_rows_in_use,&LOCK_delayed_status);