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; ...@@ -34,11 +34,11 @@ create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
let $table=t1; let $table=t1;
let $count=0; let $count=0;
insert delayed into t1 values (207); insert /* before delayed */ delayed /* after delayed */ into t1 values (207);
inc $count; inc $count;
--source include/wait_until_rows_count.inc --source include/wait_until_rows_count.inc
insert delayed into t1 values (null); insert /*! delayed */ into t1 values (null);
inc $count; inc $count;
--source include/wait_until_rows_count.inc --source include/wait_until_rows_count.inc
......
...@@ -1218,8 +1218,8 @@ master-bin.000001 # Delete_rows # # table_id: # flags: STMT_END_F ...@@ -1218,8 +1218,8 @@ master-bin.000001 # Delete_rows # # table_id: # flags: STMT_END_F
master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # COMMIT
drop table t1,t2,t3,tt1; drop table t1,t2,t3,tt1;
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
insert delayed into t1 values (207); insert /* before delayed */ delayed /* after delayed */ into t1 values (207);
insert delayed into t1 values (null); insert /*! delayed */ into t1 values (null);
insert delayed into t1 values (300); insert delayed into t1 values (300);
FLUSH TABLES; FLUSH TABLES;
show binlog events from <binlog_start>; show binlog events from <binlog_start>;
......
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
insert delayed into t1 values (207); insert /* before delayed */ delayed /* after delayed */ into t1 values (207);
insert delayed into t1 values (null); insert /*! delayed */ into t1 values (null);
insert delayed into t1 values (300); insert delayed into t1 values (300);
FLUSH TABLES; FLUSH TABLES;
show binlog events from <binlog_start>; show binlog events from <binlog_start>;
...@@ -10,14 +10,14 @@ master-bin.000001 # Query # # use `mtr`; INSERT INTO test_suppressions (pattern) ...@@ -10,14 +10,14 @@ master-bin.000001 # Query # # use `mtr`; INSERT INTO test_suppressions (pattern)
master-bin.000001 # Query # # COMMIT 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 # # 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 # # 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 # # COMMIT
master-bin.000001 # Query # # BEGIN master-bin.000001 # Query # # BEGIN
master-bin.000001 # Intvar # # INSERT_ID=208 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 # # COMMIT
master-bin.000001 # Query # # BEGIN 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 # # COMMIT
master-bin.000001 # Query # # use `test`; FLUSH TABLES master-bin.000001 # Query # # use `test`; FLUSH TABLES
RESET MASTER; RESET MASTER;
......
...@@ -717,8 +717,8 @@ master-bin.000001 # Query # # use `mysql`; DELETE FROM user WHERE host='localhos ...@@ -717,8 +717,8 @@ master-bin.000001 # Query # # use `mysql`; DELETE FROM user WHERE host='localhos
master-bin.000001 # Query # # COMMIT master-bin.000001 # Query # # COMMIT
drop table t1,t2,t3,tt1; drop table t1,t2,t3,tt1;
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
insert delayed into t1 values (207); insert /* before delayed */ delayed /* after delayed */ into t1 values (207);
insert delayed into t1 values (null); insert /*! delayed */ into t1 values (null);
insert delayed into t1 values (300); insert delayed into t1 values (300);
FLUSH TABLES; FLUSH TABLES;
show binlog events from <binlog_start>; show binlog events from <binlog_start>;
......
...@@ -51,8 +51,8 @@ CREATE TABLE t1(a int, UNIQUE(a)); ...@@ -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);
INSERT DELAYED IGNORE INTO t1 VALUES(1); INSERT DELAYED IGNORE INTO t1 VALUES(1);
flush table t1; flush table t1;
use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) use `test`; INSERT IGNORE INTO t1 VALUES(1)
use `test`; INSERT DELAYED IGNORE INTO t1 VALUES(1) use `test`; INSERT IGNORE INTO t1 VALUES(1)
select * from t1; select * from t1;
a a
1 1
...@@ -60,10 +60,10 @@ On slave ...@@ -60,10 +60,10 @@ On slave
show binlog events in 'slave-bin.000002' from <binlog_start> limit 1,6; show binlog events in 'slave-bin.000002' from <binlog_start> limit 1,6;
Log_name Pos Event_type Server_id End_log_pos Info Log_name Pos Event_type Server_id End_log_pos Info
slave-bin.000002 # Query # # BEGIN 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 # # COMMIT
slave-bin.000002 # Query # # BEGIN 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 # # COMMIT
select * from t1; select * from t1;
a a
......
...@@ -420,8 +420,7 @@ void prepare_triggers_for_insert_stmt(TABLE *table) ...@@ -420,8 +420,7 @@ void prepare_triggers_for_insert_stmt(TABLE *table)
static static
void upgrade_lock_type(THD *thd, thr_lock_type *lock_type, void upgrade_lock_type(THD *thd, thr_lock_type *lock_type,
enum_duplicates duplic, enum_duplicates duplic)
bool is_multi_insert)
{ {
if (duplic == DUP_UPDATE || if (duplic == DUP_UPDATE ||
(duplic == DUP_REPLACE && *lock_type == TL_WRITE_CONCURRENT_INSERT)) (duplic == DUP_REPLACE && *lock_type == TL_WRITE_CONCURRENT_INSERT))
...@@ -470,10 +469,9 @@ void upgrade_lock_type(THD *thd, thr_lock_type *lock_type, ...@@ -470,10 +469,9 @@ void upgrade_lock_type(THD *thd, thr_lock_type *lock_type,
return; return;
} }
bool log_on= (thd->variables.option_bits & OPTION_BIN_LOG || bool log_on= (thd->variables.option_bits & OPTION_BIN_LOG);
! (thd->security_ctx->master_access & SUPER_ACL));
if (global_system_variables.binlog_format == BINLOG_FORMAT_STMT && 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: Statement-based binary logging does not work in this case, because:
...@@ -677,8 +675,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -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 By default, both logs are enabled (this won't cause problems if the server
runs without --log-bin). runs without --log-bin).
*/ */
bool log_on= ((thd->variables.option_bits & OPTION_BIN_LOG) || bool log_on= (thd->variables.option_bits & OPTION_BIN_LOG);
(!(thd->security_ctx->master_access & SUPER_ACL)));
#endif #endif
thr_lock_type lock_type; thr_lock_type lock_type;
Item *unused_conds= 0; Item *unused_conds= 0;
...@@ -688,8 +685,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -688,8 +685,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
Upgrade lock type if the requested lock is incompatible with Upgrade lock type if the requested lock is incompatible with
the current connection mode or table operation. the current connection mode or table operation.
*/ */
upgrade_lock_type(thd, &table_list->lock_type, duplic, upgrade_lock_type(thd, &table_list->lock_type, duplic);
values_list.elements > 1);
/* /*
We can't write-delayed into a table locked with LOCK TABLES: 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, ...@@ -1022,7 +1018,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
DBUG_ASSERT(thd->killed != THD::KILL_BAD_DATA || error > 0); DBUG_ASSERT(thd->killed != THD::KILL_BAD_DATA || error > 0);
if (was_insert_delayed && table_list->lock_type == TL_WRITE) 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; String log_query;
if (create_insert_stmt_from_insert_delayed(thd, &log_query)) if (create_insert_stmt_from_insert_delayed(thd, &log_query))
{ {
...@@ -1905,22 +1901,6 @@ public: ...@@ -1905,22 +1901,6 @@ public:
thd.command=COM_DELAYED_INSERT; thd.command=COM_DELAYED_INSERT;
thd.lex->current_select= 0; // for my_message_sql thd.lex->current_select= 0; // for my_message_sql
thd.lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock() 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 Prevent changes to global.lock_wait_timeout from affecting
delayed insert threads as any timeouts in delayed inserts delayed insert threads as any timeouts in delayed inserts
...@@ -2650,11 +2630,11 @@ pthread_handler_t handle_delayed_insert(void *arg) ...@@ -2650,11 +2630,11 @@ pthread_handler_t handle_delayed_insert(void *arg)
} }
thd->lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock() thd->lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock()
/* /*
Statement-based replication of INSERT DELAYED has problems with RAND() INSERT DELAYED has to go to row-based format because the time
and user vars, so in mixed mode we go to row-based. 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(); thd->set_current_stmt_binlog_format_row_if_mixed();
/* /*
...@@ -2921,6 +2901,13 @@ bool Delayed_insert::handle_inserts(void) ...@@ -2921,6 +2901,13 @@ bool Delayed_insert::handle_inserts(void)
(ulong) row->query.length)); (ulong) row->query.length));
if (log_query) 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. This is the first value of an INSERT statement.
It is the right place to clear a forced insert_id. It is the right place to clear a forced insert_id.
...@@ -2988,39 +2975,6 @@ bool Delayed_insert::handle_inserts(void) ...@@ -2988,39 +2975,6 @@ bool Delayed_insert::handle_inserts(void)
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); 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) if (table->s->blob_fields)
free_delayed_insert_blobs(table); free_delayed_insert_blobs(table);
thread_safe_decrement(delayed_rows_in_use,&LOCK_delayed_status); 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