Commit 08db5f7e authored by 's avatar

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.
parent 30376d28
......@@ -34,11 +34,11 @@ create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
let $table=t1;
let $count=0;
insert delayed into t1 values (207);
insert /* before delayed */ delayed /* after delayed */ into t1 values (207);
inc $count;
--source include/wait_until_rows_count.inc
insert delayed into t1 values (null);
insert /*! delayed */ into t1 values (null);
inc $count;
--source include/wait_until_rows_count.inc
......
......@@ -1218,8 +1218,8 @@ master-bin.000001 # Delete_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # COMMIT
drop table t1,t2,t3,tt1;
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
insert delayed into t1 values (207);
insert delayed into t1 values (null);
insert /* before delayed */ delayed /* after delayed */ into t1 values (207);
insert /*! delayed */ into t1 values (null);
insert delayed into t1 values (300);
FLUSH TABLES;
show binlog events from <binlog_start>;
......
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
insert delayed into t1 values (207);
insert delayed into t1 values (null);
insert /* before delayed */ delayed /* after delayed */ into t1 values (207);
insert /*! delayed */ into t1 values (null);
insert delayed into t1 values (300);
FLUSH TABLES;
show binlog events from <binlog_start>;
......@@ -10,14 +10,14 @@ master-bin.000001 # Query # # use `mtr`; INSERT INTO test_suppressions (pattern)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Query # # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam
master-bin.000001 # Query # # BEGIN
master-bin.000001 # Query # # use `test`; insert delayed into t1 values (207)
master-bin.000001 # Query # # use `test`; insert /* before delayed */ /* after delayed */ into t1 values (207)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Query # # BEGIN
master-bin.000001 # Intvar # # INSERT_ID=208
master-bin.000001 # Query # # use `test`; insert delayed into t1 values (null)
master-bin.000001 # Query # # use `test`; insert /*! */ into t1 values (null)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Query # # BEGIN
master-bin.000001 # Query # # use `test`; insert delayed into t1 values (300)
master-bin.000001 # Query # # use `test`; insert into t1 values (300)
master-bin.000001 # Query # # COMMIT
master-bin.000001 # Query # # use `test`; FLUSH TABLES
RESET MASTER;
......
......@@ -717,8 +717,8 @@ master-bin.000001 # Query # # use `mysql`; DELETE FROM user WHERE host='localhos
master-bin.000001 # Query # # COMMIT
drop table t1,t2,t3,tt1;
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
insert delayed into t1 values (207);
insert delayed into t1 values (null);
insert /* before delayed */ delayed /* after delayed */ into t1 values (207);
insert /*! delayed */ into t1 values (null);
insert delayed into t1 values (300);
FLUSH TABLES;
show binlog events from <binlog_start>;
......
......@@ -51,8 +51,8 @@ CREATE TABLE t1(a int, UNIQUE(a));
INSERT DELAYED IGNORE INTO t1 VALUES(1);
INSERT DELAYED IGNORE INTO t1 VALUES(1);
flush table t1;
use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1)
use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1)
use `test`; INSERT IGNORE INTO t1 VALUES(1)
use `test`; INSERT IGNORE INTO t1 VALUES(1)
select * from t1;
a
1
......@@ -60,10 +60,10 @@ On slave
show binlog events in 'slave-bin.000002' from <binlog_start> limit 1,6;
Log_name Pos Event_type Server_id End_log_pos Info
slave-bin.000002 # Query # # BEGIN
slave-bin.000002 # Query # # use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1)
slave-bin.000002 # Query # # use `test`; INSERT IGNORE INTO t1 VALUES(1)
slave-bin.000002 # Query # # COMMIT
slave-bin.000002 # Query # # BEGIN
slave-bin.000002 # Query # # use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1)
slave-bin.000002 # Query # # use `test`; INSERT IGNORE INTO t1 VALUES(1)
slave-bin.000002 # Query # # COMMIT
select * from t1;
a
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment