diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-03-19 16:04:59 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-03-19 16:04:59 +0200 |
commit | 117291db8b35ddb4cd8c89ee4d8de888160b7163 (patch) | |
tree | 05041fcbc5a4c5c14531d148505216cb88add73c /sql | |
parent | 26e5bff00318272c717561e7b980036df3332d7b (diff) | |
parent | a77e2668667e46d96c445a4a9a8325b7fe9461b3 (diff) | |
download | mariadb-git-117291db8b35ddb4cd8c89ee4d8de888160b7163.tar.gz |
Merge 10.2 into 10.3
Diffstat (limited to 'sql')
-rw-r--r-- | sql/log.cc | 51 | ||||
-rw-r--r-- | sql/sql_class.cc | 2 | ||||
-rw-r--r-- | sql/sql_class.h | 8 | ||||
-rw-r--r-- | sql/sql_load.cc | 48 | ||||
-rw-r--r-- | sql/sql_plugin_services.ic | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 3 | ||||
-rw-r--r-- | sql/wsrep_dummy.cc | 6 | ||||
-rw-r--r-- | sql/wsrep_hton.cc | 1 | ||||
-rw-r--r-- | sql/wsrep_thd.cc | 10 |
9 files changed, 111 insertions, 20 deletions
diff --git a/sql/log.cc b/sql/log.cc index 0018ce2cdc6..23ef3152843 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6474,8 +6474,25 @@ err: it's list before dump-thread tries to send it */ update_binlog_end_pos(offset); + /* + If a transaction with the LOAD DATA statement is divided + into logical mini-transactions (of the 10K rows) and binlog + is rotated, then the last portion of data may be lost due to + wsrep handler re-registration at the boundary of the split. + Since splitting of the LOAD DATA into mini-transactions is + logical, we should not allow these mini-transactions to fall + into separate binlogs. Therefore, it is necessary to prohibit + the rotation of binlog in the middle of processing LOAD DATA: + */ +#ifdef WITH_WSREP + if (!thd->wsrep_split_flag) + { +#endif /* WITH_WSREP */ if (unlikely((error= rotate(false, &check_purge)))) check_purge= false; +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ } } } @@ -7201,8 +7218,25 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd) likely(!(error= flush_and_sync(0)))) { update_binlog_end_pos(); + /* + If a transaction with the LOAD DATA statement is divided + into logical mini-transactions (of the 10K rows) and binlog + is rotated, then the last portion of data may be lost due to + wsrep handler re-registration at the boundary of the split. + Since splitting of the LOAD DATA into mini-transactions is + logical, we should not allow these mini-transactions to fall + into separate binlogs. Therefore, it is necessary to prohibit + the rotation of binlog in the middle of processing LOAD DATA: + */ +#ifdef WITH_WSREP + if (!thd->wsrep_split_flag) + { +#endif /* WITH_WSREP */ if (unlikely((error= rotate(false, &check_purge)))) check_purge= false; +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ } offset= my_b_tell(&log_file); @@ -7969,6 +8003,20 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader) mark_xids_active(binlog_id, xid_count); } + /* + If a transaction with the LOAD DATA statement is divided + into logical mini-transactions (of the 10K rows) and binlog + is rotated, then the last portion of data may be lost due to + wsrep handler re-registration at the boundary of the split. + Since splitting of the LOAD DATA into mini-transactions is + logical, we should not allow these mini-transactions to fall + into separate binlogs. Therefore, it is necessary to prohibit + the rotation of binlog in the middle of processing LOAD DATA: + */ +#ifdef WITH_WSREP + if (!leader->thd->wsrep_split_flag) + { +#endif /* WITH_WSREP */ if (rotate(false, &check_purge)) { /* @@ -7988,6 +8036,9 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader) my_error(ER_ERROR_ON_WRITE, MYF(ME_NOREFRESH), name, errno); check_purge= false; } +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ /* In case of binlog rotate, update the correct current binlog offset. */ commit_offset= my_b_write_tell(&log_file); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 4ff57856cd9..051abb66c0c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -787,6 +787,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock) wsrep_affected_rows = 0; wsrep_replicate_GTID = false; wsrep_skip_wsrep_GTID = false; + wsrep_split_flag = false; #endif /* Call to init() below requires fully initialized Open_tables_state. */ reset_open_tables_state(this); @@ -1239,6 +1240,7 @@ void THD::init(bool skip_lock) wsrep_affected_rows = 0; wsrep_replicate_GTID = false; wsrep_skip_wsrep_GTID = false; + wsrep_split_flag = false; #endif /* WITH_WSREP */ if (variables.sql_log_bin) diff --git a/sql/sql_class.h b/sql/sql_class.h index e8083c5981b..1ac422f40b3 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -4727,6 +4727,14 @@ public: ulong wsrep_affected_rows; bool wsrep_replicate_GTID; bool wsrep_skip_wsrep_GTID; + /* This flag is set when innodb do an intermediate commit to + processing the LOAD DATA INFILE statement by splitting it into 10K + rows chunks. If flag is set, then binlog rotation is not performed + while intermediate transaction try to commit, because in this case + rotation causes unregistration of innodb handler. Later innodb handler + registered again, but replication of last chunk of rows is skipped + by the innodb engine: */ + bool wsrep_split_flag; #endif /* WITH_WSREP */ /* Handling of timeouts for commands */ diff --git a/sql/sql_load.cc b/sql/sql_load.cc index b7e110e4b95..92ef222c8b7 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -41,6 +41,7 @@ #include "sql_trigger.h" #include "sql_derived.h" #include "sql_show.h" +#include "debug_sync.h" extern "C" int _my_b_net_read(IO_CACHE *info, uchar *Buffer, size_t Count); @@ -119,16 +120,26 @@ static bool wsrep_load_data_split(THD *thd, const TABLE *table, if (hton->db_type != DB_TYPE_INNODB) DBUG_RETURN(false); WSREP_DEBUG("intermediate transaction commit in LOAD DATA"); + wsrep_set_load_multi_commit(thd, true); if (wsrep_run_wsrep_commit(thd, true) != WSREP_TRX_OK) DBUG_RETURN(true); if (binlog_hton->commit(binlog_hton, thd, true)) DBUG_RETURN(true); wsrep_post_commit(thd, true); hton->commit(hton, thd, true); + wsrep_set_load_multi_commit(thd, false); + DEBUG_SYNC(thd, "intermediate_transaction_commit"); table->file->extra(HA_EXTRA_FAKE_START_STMT); } DBUG_RETURN(false); } -# define WSREP_LOAD_DATA_SPLIT(thd,table,info) \ +/* + If the commit fails, then an early return from + the function occurs there and therefore we need + to reset the table->auto_increment_field_not_null + flag, which is usually reset after calling + the write_record(): +*/ +#define WSREP_LOAD_DATA_SPLIT(thd,table,info) \ if (wsrep_load_data_split(thd,table,info)) \ { \ table->auto_increment_field_not_null= FALSE; \ @@ -138,6 +149,14 @@ static bool wsrep_load_data_split(THD *thd, const TABLE *table, #define WSREP_LOAD_DATA_SPLIT(thd,table,info) /* empty */ #endif /* WITH_WSREP */ +#define WRITE_RECORD(thd,table,info) \ + do { \ + int err_= write_record(thd, table, &info); \ + table->auto_increment_field_not_null= FALSE; \ + if (err_) \ + DBUG_RETURN(1); \ + } while (0) + class READ_INFO: public Load_data_param { File file; @@ -918,7 +937,7 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, List_iterator_fast<Item> it(fields_vars); Item *item; TABLE *table= table_list->table; - bool err, progress_reports; + bool progress_reports; ulonglong counter, time_to_report_progress; DBUG_ENTER("read_fixed_length"); @@ -1010,11 +1029,8 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, } WSREP_LOAD_DATA_SPLIT(thd, table, info); - err= write_record(thd, table, &info); - table->auto_increment_field_not_null= FALSE; - if (err) - DBUG_RETURN(1); - + WRITE_RECORD(thd, table, info); + /* We don't need to reset auto-increment field since we are restoring its default value at the beginning of each loop iteration. @@ -1047,7 +1063,7 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, Item *item; TABLE *table= table_list->table; uint enclosed_length; - bool err, progress_reports; + bool progress_reports; ulonglong counter, time_to_report_progress; DBUG_ENTER("read_sep_field"); @@ -1153,10 +1169,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, } WSREP_LOAD_DATA_SPLIT(thd, table, info); - err= write_record(thd, table, &info); - table->auto_increment_field_not_null= FALSE; - if (err) - DBUG_RETURN(1); + WRITE_RECORD(thd, table, info); + /* We don't need to reset auto-increment field since we are restoring its default value at the beginning of each loop iteration. @@ -1200,7 +1214,6 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, for ( ; ; it.rewind()) { - bool err; if (thd->killed) { thd->send_kill_message(); @@ -1274,13 +1287,10 @@ read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, case VIEW_CHECK_ERROR: DBUG_RETURN(-1); } - + WSREP_LOAD_DATA_SPLIT(thd, table, info); - err= write_record(thd, table, &info); - table->auto_increment_field_not_null= false; - if (err) - DBUG_RETURN(1); - + WRITE_RECORD(thd, table, info); + /* We don't need to reset auto-increment field since we are restoring its default value at the beginning of each loop iteration. diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic index db73dbb6913..57600e1b4eb 100644 --- a/sql/sql_plugin_services.ic +++ b/sql/sql_plugin_services.ic @@ -180,6 +180,8 @@ static struct wsrep_service_st wsrep_handler = { wsrep_thd_trx_seqno, wsrep_thd_ws_handle, wsrep_thd_auto_increment_variables, + wsrep_set_load_multi_commit, + wsrep_is_load_multi_commit, wsrep_trx_is_aborting, wsrep_trx_order_before, wsrep_unlock_rollback, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7ce4ea49c73..6915d4d23ca 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -21264,7 +21264,8 @@ make_cond_for_table_from_pred(THD *thd, Item *root_cond, Item *cond, the new parent Item. This should not be expensive because all children of Item_cond_and should be fixed by now. */ - new_cond->fix_fields(thd, 0); + if (new_cond->fix_fields(thd, 0)) + return (COND*) 0; new_cond->used_tables_cache= ((Item_cond_and*) cond)->used_tables_cache & tables; diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc index 9afdb36a643..97ec85f7566 100644 --- a/sql/wsrep_dummy.cc +++ b/sql/wsrep_dummy.cc @@ -142,6 +142,12 @@ void wsrep_thd_auto_increment_variables(THD *thd, *increment= thd->variables.auto_increment_increment; } +void wsrep_set_load_multi_commit(THD *thd, bool split) +{ } + +bool wsrep_is_load_multi_commit(THD *thd) +{ return false; } + int wsrep_trx_is_aborting(THD *) { return 0; } diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc index 8110faf7d11..aa8dff8d188 100644 --- a/sql/wsrep_hton.cc +++ b/sql/wsrep_hton.cc @@ -46,6 +46,7 @@ void wsrep_cleanup_transaction(THD *thd) thd->wsrep_exec_mode= LOCAL_STATE; thd->wsrep_affected_rows= 0; thd->wsrep_skip_wsrep_GTID= false; + thd->wsrep_split_flag= false; return; } diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index f28063849ea..df09610b66b 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -707,3 +707,13 @@ my_bool wsrep_thd_is_applier(MYSQL_THD thd) return (is_applier); } + +void wsrep_set_load_multi_commit(THD *thd, bool split) +{ + thd->wsrep_split_flag= split; +} + +bool wsrep_is_load_multi_commit(THD *thd) +{ + return thd->wsrep_split_flag; +} |