From 51a91166387760546d563ebf72bfa037fcff24a8 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Fri, 27 Mar 2009 13:19:50 +0800 Subject: BUG#37145 Killing a statement doing DDL may log binlog event with error code 1053 When the thread executing a DDL was killed after finished its execution but before writing the binlog event, the error code in the binlog event could be set wrongly to ER_SERVER_SHUTDOWN or ER_QUERY_INTERRUPTED. This patch fixed the problem by ignoring the kill status when constructing the event for DDL statements. This patch also included the following changes in order to provide the test case. 1) modified mysqltest to support variable for connection command 2) modified mysql-test-run.pl, add new variable MYSQL_SLAVE to run mysql client against the slave mysqld. --- sql/sql_delete.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql/sql_delete.cc') diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 38f89683065..a757b7c28a5 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -730,7 +730,7 @@ void multi_delete::send_error(uint errcode,const char *err) if (mysql_bin_log.is_open()) { Query_log_event qinfo(thd, thd->query, thd->query_length, - transactional_tables, FALSE); + transactional_tables, FALSE, THD::KILLED_NO_VALUE); mysql_bin_log.write(&qinfo); } thd->transaction.all.modified_non_trans_table= true; @@ -958,7 +958,7 @@ end: { thd->clear_error(); Query_log_event qinfo(thd, thd->query, thd->query_length, - 0, FALSE); + 0, FALSE, THD::NOT_KILLED); mysql_bin_log.write(&qinfo); } send_ok(thd); // This should return record count -- cgit v1.2.1 From a20bc967cecb9a1254c446f9179c4dc80c18464b Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Fri, 27 Mar 2009 17:08:14 +0100 Subject: Bug#40127 Multiple table DELETE IGNORE hangs on foreign key constraint violation on 5.0 The server crashes on an assert in net_end_statement indicating that the Diagnostics area wasn't set properly during execution. This happened on a multi table DELETE operation using the IGNORE keyword. The keyword is suppose to allow for execution to continue on a best effort despite some non-fatal errors. Instead execution stopped and no client response was sent which would have led to a protocol error if it hadn't been for the assert. This patch corrects this issue by checking for the existence of an IGNORE option before setting an error state during row-by-row delete iteration. mysql-test/r/innodb_mysql.result: * Added test case for bug40127 mysql-test/t/innodb_mysql.test: * Added test case for bug40127 sql/sql_delete.cc: * IGNORE option wasn't implemented in multi_delete::send_data and multi_delete::do_deletes --- sql/sql_delete.cc | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) (limited to 'sql/sql_delete.cc') diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d87eafa3e0c..1b42e522491 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -709,6 +709,8 @@ bool multi_delete::send_data(List &values) TABLE_LIST *del_table; DBUG_ENTER("multi_delete::send_data"); + bool ignore= thd->lex->current_select->no_error; + for (del_table= delete_tables; del_table; del_table= del_table->next_local, secure_counter++) @@ -741,8 +743,12 @@ bool multi_delete::send_data(List &values) TRG_ACTION_AFTER, FALSE)) DBUG_RETURN(1); } - else + else if (!ignore) { + /* + If the IGNORE option is used errors caused by ha_delete_row don't + have to stop the iteration. + */ table->file->print_error(error,MYF(0)); DBUG_RETURN(1); } @@ -834,6 +840,11 @@ int multi_delete::do_deletes() { int local_error= 0, counter= 0, tmp_error; bool will_batch; + /* + If the IGNORE option is used all non fatal errors will be translated + to warnings and we should not break the row-by-row iteration + */ + bool ignore= thd->lex->current_select->no_error; DBUG_ENTER("do_deletes"); DBUG_ASSERT(do_delete); @@ -872,18 +883,29 @@ int multi_delete::do_deletes() local_error= 1; break; } - if ((local_error=table->file->ha_delete_row(table->record[0]))) + + local_error= table->file->ha_delete_row(table->record[0]); + if (local_error && !ignore) { - table->file->print_error(local_error,MYF(0)); - break; + table->file->print_error(local_error,MYF(0)); + break; } - deleted++; - if (table->triggers && - table->triggers->process_triggers(thd, TRG_EVENT_DELETE, - TRG_ACTION_AFTER, FALSE)) + + /* + Increase the reported number of deleted rows only if no error occurred + during ha_delete_row. + Also, don't execute the AFTER trigger if the row operation failed. + */ + if (!local_error) { - local_error= 1; - break; + deleted++; + if (table->triggers && + table->triggers->process_triggers(thd, TRG_EVENT_DELETE, + TRG_ACTION_AFTER, FALSE)) + { + local_error= 1; + break; + } } } if (will_batch && (tmp_error= table->file->end_bulk_delete())) -- cgit v1.2.1 From 609a794b15fe44408fa47582e798147d1ffe3463 Mon Sep 17 00:00:00 2001 From: Anurag Shekhar Date: Wed, 6 May 2009 13:37:10 +0530 Subject: Bug #39918 memory (heap) engine crashing with b-tree index and DELETE with seg fault Multiple-table DELETE from a table joined to itself may cause server crash. This was originally discovered with MEMORY engine, but may affect other engines with different symptoms. The problem was that the server violated SE API by performing parallel table scan in one handler and removing records in another (delete on the fly optimization). mysql-test/r/heap_btree.result: Updated test result after adding new test for this bug. mysql-test/t/heap_btree.test: Updated test result after adding new test for the bug report. sql/sql_delete.cc: Updated to check if the files in delete list appears in join list and disable delete while scanning, if it appears. --- sql/sql_delete.cc | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'sql/sql_delete.cc') diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index a757b7c28a5..5307a4426c5 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -503,6 +503,11 @@ int mysql_multi_delete_prepare(THD *thd) } } } + /* + Reset the exclude flag to false so it doesn't interfare + with further calls to unique_table + */ + lex->select_lex.exclude_from_table_unique_test= FALSE; DBUG_RETURN(FALSE); } @@ -538,11 +543,24 @@ multi_delete::initialize_tables(JOIN *join) DBUG_RETURN(1); table_map tables_to_delete_from=0; + delete_while_scanning= 1; for (walk= delete_tables; walk; walk= walk->next_local) + { tables_to_delete_from|= walk->table->map; + if (delete_while_scanning && + unique_table(thd, walk, join->tables_list, false)) + { + /* + If the table we are going to delete from appears + in join, we need to defer delete. So the delete + doesn't interfers with the scaning of results. + */ + delete_while_scanning= 0; + } + } + walk= delete_tables; - delete_while_scanning= 1; for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables; tab < end; tab++) -- cgit v1.2.1 From abf5f8dac2a0840687dc99816cbd68fb8c515e50 Mon Sep 17 00:00:00 2001 From: He Zhenxing Date: Sat, 30 May 2009 21:32:28 +0800 Subject: BUG#41948 Query_log_event constructor needlessly contorted Make the caller of Query_log_event, Execute_load_log_event constructors and THD::binlog_query to provide the error code instead of having the constructors to figure out the error code. sql/log_event.cc: Changed constructors of Query_log_event and Execute_load_log_event to accept the error code argument instead of figuring it out by itself sql/log_event.h: Changed constructors of Query_log_event and Execute_load_log_event to accept the error code argument --- sql/sql_delete.cc | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'sql/sql_delete.cc') diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 7b967206305..277269f3b0d 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -389,8 +389,12 @@ cleanup: FALSE : transactional_table; + int errcode= 0; if (error < 0) thd->clear_error(); + else + errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); + /* [binlog]: If 'handler::delete_all_rows()' was called and the storage engine does not inject the rows itself, we replicate @@ -402,7 +406,7 @@ cleanup: */ int log_result= thd->binlog_query(query_type, thd->query, thd->query_length, - is_trans, FALSE, killed_status); + is_trans, FALSE, errcode); if (log_result && transactional_table) { @@ -836,9 +840,10 @@ void multi_delete::abort() */ if (mysql_bin_log.is_open()) { + int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length, - transactional_tables, FALSE); + transactional_tables, FALSE, errcode); } thd->transaction.all.modified_non_trans_table= true; } @@ -979,11 +984,14 @@ bool multi_delete::send_eof() { if (mysql_bin_log.is_open()) { + int errcode= 0; if (local_error == 0) thd->clear_error(); + else + errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length, - transactional_tables, FALSE, killed_status) && + transactional_tables, FALSE, errcode) && !normal_tables) { local_error=1; // Log write failed: roll back the SQL statement -- cgit v1.2.1 From a10350978814ec7f7ba7e64f6615847e0311cc69 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Wed, 10 Jun 2009 16:04:07 +0200 Subject: Bug #43414 Parenthesis (and other) warnings compiling MySQL with gcc 4.3.2 Compiling MySQL with gcc 4.3.2 and later produces a number of warnings, many of which are new with the recent compiler versions. This bug will be resolved in more than one patch to limit the size of changesets. This is the second patch, fixing more of the warnings. --- sql/sql_delete.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/sql_delete.cc') diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 79fc4872f05..30b14209a7c 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -711,7 +711,7 @@ void multi_delete::send_error(uint errcode,const char *err) /* the error was handled or nothing deleted and no side effects return */ if (error_handled || - !thd->transaction.stmt.modified_non_trans_table && !deleted) + (!thd->transaction.stmt.modified_non_trans_table && !deleted)) DBUG_VOID_RETURN; /* Something already deleted so we have to invalidate cache */ -- cgit v1.2.1 From 3b0e6e41098557dab9fe7ca5c59f2863fd671b94 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Wed, 17 Jun 2009 15:54:01 +0200 Subject: Bug #43414 Parenthesis (and other) warnings compiling MySQL with gcc 4.3.2 Compiling MySQL with gcc 4.3.2 and later produces a number of warnings, many of which are new with the recent compiler versions. This bug will be resolved in more than one patch to limit the size of changesets. This is the second patch, fixing more of the warnings. --- sql/sql_delete.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/sql_delete.cc') diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 79fc4872f05..30b14209a7c 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -711,7 +711,7 @@ void multi_delete::send_error(uint errcode,const char *err) /* the error was handled or nothing deleted and no side effects return */ if (error_handled || - !thd->transaction.stmt.modified_non_trans_table && !deleted) + (!thd->transaction.stmt.modified_non_trans_table && !deleted)) DBUG_VOID_RETURN; /* Something already deleted so we have to invalidate cache */ -- cgit v1.2.1 From 3cf052b76cb62a3efbb29d4086a893f7f0d37d94 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Thu, 18 Jun 2009 14:52:46 +0100 Subject: BUG#43929 binlog corruption when max_binlog_cache_size is exceeded Large transactions and statements may corrupt the binary log if the size of the cache, which is set by the max_binlog_cache_size, is not enough to store the the changes. In a nutshell, to fix the bug, we save the position of the next character in the cache before starting processing a statement. If there is a problem, we simply restore the position thus removing any effect of the statement from the cache. Unfortunately, to avoid corrupting the binary log, we may end up loosing changes on non-transactional tables if they do not fit in the cache. In such cases, we store an Incident_log_event in order to stop the slave and alert users that some changes were not logged. Precisely, for every non-transactional changes that do not fit into the cache, we do the following: a) the statement is *not* logged b) an incident event is logged after committing/rolling back the transaction, if any. Note that if a failure happens before writing the incident event to the binary log, the slave will not stop and the master will not have reported any error. c) its respective statement gives an error For transactional changes that do not fit into the cache, we do the following: a) the statement is *not* logged b) its respective statement gives an error To work properly, this patch requires two additional things. Firstly, callers to MYSQL_BIN_LOG::write and THD::binlog_query must handle any error returned and take the appropriate actions such as undoing the effects of a statement. We already changed some calls in the sql_insert.cc, sql_update.cc and sql_insert.cc modules but the remaining calls spread all over the code should be handled in BUG#37148. Secondly, statements must be either classified as DDL or DML because DDLs that do not get into the cache must generate an incident event since they cannot be rolled back. --- sql/sql_delete.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql/sql_delete.cc') diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 277269f3b0d..f9de43347bc 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -408,7 +408,7 @@ cleanup: thd->query, thd->query_length, is_trans, FALSE, errcode); - if (log_result && transactional_table) + if (log_result) { error=1; } -- cgit v1.2.1 From 9347649c16c176605aac1e36275fa89a6b21f9fc Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Fri, 19 Jun 2009 13:24:43 +0500 Subject: Bug#44834 strxnmov is expected to behave as you'd expect The problem: described in the bug report. The fix: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used client/mysql.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/ha_ndbcluster.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/ha_ndbcluster_binlog.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/handler.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/log.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/mysqld.cc: removed unnecessary line sql/parse_file.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/sql_acl.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/sql_base.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/sql_db.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/sql_delete.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/sql_partition.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/sql_rename.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/sql_show.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/sql_table.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function sql/sql_view.cc: --increase buffers where it's necessary (buffers which are used in stxnmov) --decrease buffer lengths which are used as argument for strxnmov function --- sql/sql_delete.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sql/sql_delete.cc') diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index b20ff78b9ba..677098d275a 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1051,7 +1051,7 @@ static bool mysql_truncate_by_delete(THD *thd, TABLE_LIST *table_list) bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) { HA_CREATE_INFO create_info; - char path[FN_REFLEN]; + char path[FN_REFLEN + 1]; TABLE *table; bool error; uint path_length; @@ -1088,7 +1088,7 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) goto end; } - path_length= build_table_filename(path, sizeof(path), table_list->db, + path_length= build_table_filename(path, sizeof(path) - 1, table_list->db, table_list->table_name, reg_ext, 0); if (!dont_send_ok) -- cgit v1.2.1 From 410e1a72b957b72e0fb2a50930e7e82847c4486c Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 13 Jul 2009 18:11:16 +0300 Subject: Bug #40113: Embedded SELECT inside UPDATE or DELETE can timeout without error When using quick access methods for searching rows in UPDATE or DELETE there was no check if a fatal error was not already sent to the client while evaluating the quick condition. As a result a false OK (following the error) was sent to the client and the error was thus transformed into a warning. Fixed by checking for errors sent to the client during SQL_SELECT::check_quick() and treating them as real errors. Fixed a wrong test case in group_min_max.test Fixed a wrong return code in mysql_update() and mysql_delete() mysql-test/r/bug40113.result: Bug #40013: test case mysql-test/r/group_min_max.result: Bug #40013: fixed a wrong test case mysql-test/t/bug40113-master.opt: Bug #40013: test case mysql-test/t/bug40113.test: Bug #40013: test case mysql-test/t/group_min_max.test: Bug #40013: fixed a wrong test case sql/sql_delete.cc: Bug #40113: check for errors evaluating the quick select sql/sql_update.cc: Bug #40113: check for errors evaluating the quick select --- sql/sql_delete.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'sql/sql_delete.cc') diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 30b14209a7c..3bf088609cd 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -144,6 +144,14 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, delete select; free_underlaid_joins(thd, select_lex); thd->row_count_func= 0; + /* + Error was already created by quick select evaluation (check_quick()). + TODO: Add error code output parameter to Item::val_xxx() methods. + Currently they rely on the user checking DA for + errors when unwinding the stack after calling Item::val_xxx(). + */ + if (thd->net.report_error) + DBUG_RETURN(TRUE); send_ok(thd,0L); /* @@ -407,7 +415,7 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) if (select_lex->inner_refs_list.elements && fix_inner_refs(thd, all_fields, select_lex, select_lex->ref_pointer_array)) - DBUG_RETURN(-1); + DBUG_RETURN(TRUE); select_lex->fix_prepare_information(thd, conds, &fake_conds); DBUG_RETURN(FALSE); -- cgit v1.2.1