diff options
author | unknown <aelkin/elkin@koti.dsl.inet.fi> | 2007-10-29 15:20:59 +0200 |
---|---|---|
committer | unknown <aelkin/elkin@koti.dsl.inet.fi> | 2007-10-29 15:20:59 +0200 |
commit | 95f3db7be1b3425b47f34090f33c7eeb52f97703 (patch) | |
tree | 7ee3c865779ddc72072daa205d4b5d3c3c0280fa /sql/sql_delete.cc | |
parent | c8b6d1050933f0b9b18367c421702c9f16907de5 (diff) | |
download | mariadb-git-95f3db7be1b3425b47f34090f33c7eeb52f97703.tar.gz |
Bug #27571 asynchronousity in setting mysql_`query`::error and
Query_log_event::error_code
A query can perform completely having the local var error of mysql_$query
zero, where $query in insert, update, delete, load,
and be binlogged with error_code e.g KILLED_QUERY while there is no
reason do to so.
That can happen because Query_log_event consults thd->killed flag to
evaluate error_code.
Fixed with implementing a scheme suggested and partly implemented at
time of bug@22725 work-on. error_status is cached immediatly after the
control leaves the main rows-loop and that instance always corresponds
to `error' the local of mysql_$query functions. The cached value
is passed to Query_log_event constructor, not the default thd->killed
which can be changed in between of the caching and the constructing.
mysql-test/r/binlog_killed.result:
results changed
mysql-test/t/binlog_killed.test:
Demonstrating that effective killing during rows-loop execution leads to the speficied actions:
binlogging with the error for a query modified a not-transactional table or
rolling back effects for transactional table;
fixing possible non-determinism with ID when query_log_enabled;
leave commented out tests for multi-update,delete due to another bug;
removing an obsolete tests template;
changing system rm to --remove_file.
sql/log_event.cc:
adding killed status arg
sql/log_event.h:
added killed status arg
sql/sql_delete.cc:
deploying the update part patch for delete, multi-delete
sql/sql_insert.cc:
deploying the update-part patch for insert..select
sql/sql_load.cc:
deploying the update-part patch for load data.
simulation added.
sql/sql_update.cc:
Impementing the fix as described in the comments left by bug@22725.
Also simulation of killing after the loop that would affect binlogging in the old code.
mysql-test/t/binlog_killed_bug27571-master.opt:
post rows-loop killing simulation's options
mysql-test/t/binlog_killed_bug27571.test:
Checking that if killing happens inbetween of the end of rows loop and
recording into binlog that will not lead to recording any error incl
the killed error.
mysql-test/t/binlog_killed_simulate-master.opt:
simulation options
mysql-test/t/binlog_killed_simulate.test:
tests for
a query (update is choosen) being killed after the row-loop;
load data killed within the loop - effective killed error in the event is gained.
Diffstat (limited to 'sql/sql_delete.cc')
-rw-r--r-- | sql/sql_delete.cc | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index add37c8c552..a28a39a769d 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -38,6 +38,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ha_rows deleted; uint usable_index= MAX_KEY; SELECT_LEX *select_lex= &thd->lex->select_lex; + THD::killed_state killed_status= THD::NOT_KILLED; DBUG_ENTER("mysql_delete"); if (open_and_lock_tables(thd, table_list)) @@ -280,8 +281,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, else table->file->unlock_row(); // Row failed selection, release lock on it } - if (thd->killed && !error) - error= 1; // Aborted + killed_status= thd->killed; + error= (killed_status == THD::NOT_KILLED)? error : 1; thd->proc_info="end"; end_read_record(&info); free_io_cache(table); // Will not do any harm @@ -326,7 +327,7 @@ cleanup: if (error < 0) thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_table, FALSE); + transactional_table, FALSE, killed_status); if (mysql_bin_log.write(&qinfo) && transactional_table) error=1; } @@ -729,7 +730,8 @@ void multi_delete::send_error(uint errcode,const char *err) } thd->transaction.all.modified_non_trans_table= true; } - DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table); + DBUG_ASSERT(!normal_tables || !deleted || + thd->transaction.stmt.modified_non_trans_table); DBUG_VOID_RETURN; } @@ -817,6 +819,7 @@ int multi_delete::do_deletes() bool multi_delete::send_eof() { + THD::killed_state killed_status= THD::NOT_KILLED; thd->proc_info="deleting from reference tables"; /* Does deletes for the last n - 1 tables, returns 0 if ok */ @@ -824,7 +827,7 @@ bool multi_delete::send_eof() /* compute a total error to know if something failed */ local_error= local_error || error; - + killed_status= (local_error == 0)? THD::NOT_KILLED : thd->killed; /* reset used flags */ thd->proc_info="end"; @@ -836,7 +839,8 @@ bool multi_delete::send_eof() { query_cache_invalidate3(thd, delete_tables, 1); } - DBUG_ASSERT(!normal_tables || !deleted || thd->transaction.stmt.modified_non_trans_table); + DBUG_ASSERT(!normal_tables || !deleted || + thd->transaction.stmt.modified_non_trans_table); if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table) { if (mysql_bin_log.is_open()) @@ -844,7 +848,7 @@ bool multi_delete::send_eof() if (local_error == 0) thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_tables, FALSE); + transactional_tables, FALSE, killed_status); if (mysql_bin_log.write(&qinfo) && !normal_tables) local_error=1; // Log write failed: roll back the SQL statement } |