diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result index a053b6060c4..9532c2995ce 100644 --- a/mysql-test/main/order_by.result +++ b/mysql-test/main/order_by.result @@ -3343,6 +3343,63 @@ C B DROP TABLE t1; # +# MDEV-16214: Incorrect plan taken by the optimizer , uses INDEX instead of ref access with ORDER BY +# +create table t1(a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t2( +id int primary key, +key1 int,key2 int, +col1 int, +key(key1), key(key2) +); +insert into t2 +select +A.a + B.a*10 + C.a*100, +A.a + 10*B.a, A.a + 10*B.a, +123456 +from t1 A, t1 B, t1 C; +# here type should show ref not index +explain select +(SELECT concat(id, '-', key1, '-', col1) +FROM t2 +WHERE +t2.key1 = t1.a and t2.key1 IS NOT NULL +ORDER BY +t2.key2 ASC +LIMIT 1) +from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 10 +2 DEPENDENT SUBQUERY t2 ref key1 key1 5 test.t1.a 10 Using index condition; Using where; Using filesort +select +(SELECT concat(id, '-', key1, '-', col1) +FROM t2 +WHERE +t2.key1 = t1.a and t2.key1 IS NOT NULL +ORDER BY +t2.key2 ASC +LIMIT 1) +from t1; +(SELECT concat(id, '-', key1, '-', col1) +FROM t2 +WHERE +t2.key1 = t1.a and t2.key1 IS NOT NULL +ORDER BY +t2.key2 ASC +LIMIT 1) +900-0-123456 +901-1-123456 +902-2-123456 +903-3-123456 +904-4-123456 +905-5-123456 +906-6-123456 +907-7-123456 +908-8-123456 +909-9-123456 +drop table t1,t2; +# # MDEV-17761: Odd optimizer choice with ORDER BY LIMIT and condition selectivity # create table t1(a int); diff --git a/mysql-test/main/order_by.test b/mysql-test/main/order_by.test index 425ba8f916c..934c503302f 100644 --- a/mysql-test/main/order_by.test +++ b/mysql-test/main/order_by.test @@ -2204,6 +2204,43 @@ ORDER BY id+1 DESC; DROP TABLE t1; +--echo # +--echo # MDEV-16214: Incorrect plan taken by the optimizer , uses INDEX instead of ref access with ORDER BY +--echo # + +create table t1(a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); + +create table t2( + id int primary key, + key1 int,key2 int, + col1 int, + key(key1), key(key2) +); + +insert into t2 + select + A.a + B.a*10 + C.a*100, + A.a + 10*B.a, A.a + 10*B.a, + 123456 +from t1 A, t1 B, t1 C; + +let $query= select + (SELECT concat(id, '-', key1, '-', col1) + FROM t2 + WHERE + t2.key1 = t1.a and t2.key1 IS NOT NULL + ORDER BY + t2.key2 ASC + LIMIT 1) + from t1; + +--echo # here type should show ref not index +eval explain $query; +eval $query; + +drop table t1,t2; + --echo # --echo # MDEV-17761: Odd optimizer choice with ORDER BY LIMIT and condition selectivity --echo # diff --git a/mysql-test/suite/versioning/r/create.result b/mysql-test/suite/versioning/r/create.result index 895b2c3b66a..ce19d83fcda 100644 --- a/mysql-test/suite/versioning/r/create.result +++ b/mysql-test/suite/versioning/r/create.result @@ -520,5 +520,12 @@ row_end bigint as row end, period for system_time (row_start, row_end) ) engine=myisam with system versioning; ERROR HY000: `row_start` must be of type TIMESTAMP(6) for system-versioned table `t1` +create table t ( +a int, +row_start datetime(6) generated always as row start, +row_end datetime(6) generated always as row end, +period for system_time(row_start, row_end) +) with system versioning; +ERROR HY000: `row_start` must be of type TIMESTAMP(6) for system-versioned table `t` drop database test; create database test; diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index cf6f188372c..4413202ebcc 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -530,6 +530,25 @@ set timestamp=1523466002.799571; insert into t1 values (11),(12); set timestamp=1523466004.169435; delete from t1 where pk in (11, 12); +# +# MDEV-18136 Server crashes in Item_func_dyncol_create::prepare_arguments +# +create or replace table t1 (pk int) with system versioning +partition by system_time interval 7 second ( +partition ver_p1 history, +partition ver_pn current); +alter table t1 +partition by system_time interval column_get(column_create(7,7), 7 as int) second ( +partition ver_p1 history, +partition ver_pn current); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `pk` int(11) DEFAULT NULL +) ENGINE=DEFAULT_ENGINE DEFAULT CHARSET=latin1 WITH SYSTEM VERSIONING + PARTITION BY SYSTEM_TIME INTERVAL 7 SECOND +(PARTITION `ver_p1` HISTORY ENGINE = DEFAULT_ENGINE, + PARTITION `ver_pn` CURRENT ENGINE = DEFAULT_ENGINE) # Test cleanup drop database test; create database test; diff --git a/mysql-test/suite/versioning/r/replace.result b/mysql-test/suite/versioning/r/replace.result index 1711be5212e..4173432ff45 100644 --- a/mysql-test/suite/versioning/r/replace.result +++ b/mysql-test/suite/versioning/r/replace.result @@ -32,5 +32,19 @@ insert into t1 values (1,1); create or replace table t2 (c int); create or replace view v as select t1.* from t1 join t2; replace into v (a, b) select a, b from t1; +drop table t1; +CREATE TABLE t1 ( +pk INT AUTO_INCREMENT, +f INT, +row_start SYS_DATATYPE AS ROW START INVISIBLE, +row_end SYS_DATATYPE AS ROW END INVISIBLE, +PRIMARY KEY(pk), +UNIQUE(f), +PERIOD FOR SYSTEM_TIME(row_start, row_end) +) WITH SYSTEM VERSIONING; +INSERT INTO t1 () VALUES (),(),(),(),(),(); +UPDATE IGNORE t1 SET f = 1; +REPLACE t1 SELECT * FROM t1; +DROP TABLE t1; drop database test; create database test; diff --git a/mysql-test/suite/versioning/t/create.test b/mysql-test/suite/versioning/t/create.test index 733b5057c20..21548c557c7 100644 --- a/mysql-test/suite/versioning/t/create.test +++ b/mysql-test/suite/versioning/t/create.test @@ -387,5 +387,14 @@ create or replace table t1 ( period for system_time (row_start, row_end) ) engine=myisam with system versioning; +--error ER_VERS_FIELD_WRONG_TYPE +create table t ( + a int, + row_start datetime(6) generated always as row start, + row_end datetime(6) generated always as row end, + period for system_time(row_start, row_end) +) with system versioning; + + drop database test; create database test; diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index a9e2429b7c4..0faf32c887a 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -466,6 +466,20 @@ insert into t1 values (11),(12); set timestamp=1523466004.169435; delete from t1 where pk in (11, 12); +--echo # +--echo # MDEV-18136 Server crashes in Item_func_dyncol_create::prepare_arguments +--echo # +create or replace table t1 (pk int) with system versioning +partition by system_time interval 7 second ( + partition ver_p1 history, + partition ver_pn current); +alter table t1 +partition by system_time interval column_get(column_create(7,7), 7 as int) second ( + partition ver_p1 history, + partition ver_pn current); +--replace_result $default_engine DEFAULT_ENGINE +show create table t1; + --echo # Test cleanup drop database test; create database test; diff --git a/mysql-test/suite/versioning/t/replace.test b/mysql-test/suite/versioning/t/replace.test index bc7e084758d..391cd2a12fc 100644 --- a/mysql-test/suite/versioning/t/replace.test +++ b/mysql-test/suite/versioning/t/replace.test @@ -35,6 +35,23 @@ insert into t1 values (1,1); create or replace table t2 (c int); create or replace view v as select t1.* from t1 join t2; replace into v (a, b) select a, b from t1; +drop table t1; + +--replace_result $sys_datatype_expl SYS_DATATYPE +eval CREATE TABLE t1 ( + pk INT AUTO_INCREMENT, + f INT, + row_start $sys_datatype_expl AS ROW START INVISIBLE, + row_end $sys_datatype_expl AS ROW END INVISIBLE, + PRIMARY KEY(pk), + UNIQUE(f), + PERIOD FOR SYSTEM_TIME(row_start, row_end) +) WITH SYSTEM VERSIONING; +INSERT INTO t1 () VALUES (),(),(),(),(),(); +UPDATE IGNORE t1 SET f = 1; +REPLACE t1 SELECT * FROM t1; +DROP TABLE t1; + drop database test; create database test; diff --git a/sql/handler.cc b/sql/handler.cc index c5d6fa29f8f..124f5c8e9ce 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7650,8 +7650,7 @@ bool Vers_parse_info::check_conditions(const Lex_table_name &table_name, static bool is_versioning_timestamp(const Create_field *f) { - return (f->type_handler() == &type_handler_datetime2 || - f->type_handler() == &type_handler_timestamp2) && + return f->type_handler() == &type_handler_timestamp2 && f->length == MAX_DATETIME_FULL_WIDTH; } diff --git a/sql/partition_info.h b/sql/partition_info.h index 15c83a2439e..a2320c34048 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -401,11 +401,20 @@ public: DBUG_ASSERT(part_type == VERSIONING_PARTITION); vers_info->interval.type= int_type; vers_info->interval.start= start; - return get_interval_value(thd, item, int_type, &vers_info->interval.step) || + if (item->fix_fields_if_needed_for_scalar(thd, &item)) + return true; + bool error= get_interval_value(thd, item, int_type, &vers_info->interval.step) || vers_info->interval.step.neg || vers_info->interval.step.second_part || !(vers_info->interval.step.year || vers_info->interval.step.month || vers_info->interval.step.day || vers_info->interval.step.hour || vers_info->interval.step.minute || vers_info->interval.step.second); + if (error) + { + my_error(ER_PART_WRONG_VALUE, MYF(0), + thd->lex->create_last_non_select_table->table_name.str, + "INTERVAL"); + } + return error; } bool vers_set_limit(ulonglong limit) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fac0b03cbbc..598f46594e5 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10569,31 +10569,35 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, j->ref.null_rejecting|= (key_part_map)1 << i; keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables; /* - Todo: we should remove this check for thd->lex->describe on the next - line. With SHOW EXPLAIN code, EXPLAIN printout code no longer depends - on it. However, removing the check caused change in lots of query - plans! Does the optimizer depend on the contents of - table_ref->key_copy ? If yes, do we produce incorrect EXPLAINs? + We don't want to compute heavy expressions in EXPLAIN, an example would + select * from t1 where t1.key=(select thats very heavy); + + (select thats very heavy) => is a constant here + eg: (select avg(order_cost) from orders) => constant but expensive */ if (!keyuse->val->used_tables() && !thd->lex->describe) { // Compare against constant - store_key_item tmp(thd, + store_key_item tmp(thd, keyinfo->key_part[i].field, key_buff + maybe_null, maybe_null ? key_buff : 0, keyinfo->key_part[i].length, keyuse->val, FALSE); - if (unlikely(thd->is_fatal_error)) - DBUG_RETURN(TRUE); - tmp.copy(); + if (unlikely(thd->is_fatal_error)) + DBUG_RETURN(TRUE); + tmp.copy(); j->ref.const_ref_part_map |= key_part_map(1) << i ; } else - *ref_key++= get_store_key(thd, - keyuse,join->const_table_map, - &keyinfo->key_part[i], - key_buff, maybe_null); + { + *ref_key++= get_store_key(thd, + keyuse,join->const_table_map, + &keyinfo->key_part[i], + key_buff, maybe_null); + if (!keyuse->val->used_tables()) + j->ref.const_ref_part_map |= key_part_map(1) << i ; + } /* Remember if we are going to use REF_OR_NULL But only if field _really_ can be null i.e. we force JT_REF @@ -25925,6 +25929,15 @@ bool JOIN_TAB::save_explain_data(Explain_table_access *eta, { if (!(eta->ref_list.append_str(thd->mem_root, "const"))) return 1; + /* + create_ref_for_key() handles keypart=const equalities as follows: + - non-EXPLAIN execution will copy the "const" to lookup tuple + immediately and will not add an element to ref.key_copy + - EXPLAIN will put an element into ref.key_copy. Since we've + just printed "const" for it, we should skip it here + */ + if (thd->lex->describe) + key_ref++; } else { @@ -27661,7 +27674,15 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, */ if (ref_key >= 0 && ref_key != MAX_KEY && tab->type == JT_REF) { - if (table->quick_keys.is_set(ref_key)) + /* + If ref access uses keypart=const for all its key parts, + and quick select uses the same # of key parts, then they are equivalent. + Reuse #rows estimate from quick select as it is more precise. + */ + if (tab->ref.const_ref_part_map == + make_prev_keypart_map(tab->ref.key_parts) && + table->quick_keys.is_set(ref_key) && + table->quick_key_parts[ref_key] == tab->ref.key_parts) refkey_rows_estimate= table->quick_rows[ref_key]; else { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 54ec7e95906..6547bee15ac 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5974,12 +5974,7 @@ opt_versioning_rotation: { partition_info *part_info= Lex->part_info; if (unlikely(part_info->vers_set_interval(thd, $2, $3, $4))) - { - my_error(ER_PART_WRONG_VALUE, MYF(0), - Lex->create_last_non_select_table->table_name.str, - "INTERVAL"); MYSQL_YYABORT; - } } | LIMIT ulonglong_num { diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 89538884d2b..46b1f7c584e 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -5999,12 +5999,7 @@ opt_versioning_rotation: { partition_info *part_info= Lex->part_info; if (unlikely(part_info->vers_set_interval(thd, $2, $3, $4))) - { - my_error(ER_PART_WRONG_VALUE, MYF(0), - Lex->create_last_non_select_table->table_name.str, - "INTERVAL"); MYSQL_YYABORT; - } } | LIMIT ulonglong_num { diff --git a/sql/table.cc b/sql/table.cc index 3ed4b355cb5..699102885c2 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2314,7 +2314,6 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, switch (handler->real_field_type()) { case MYSQL_TYPE_TIMESTAMP2: - case MYSQL_TYPE_DATETIME2: break; case MYSQL_TYPE_LONGLONG: if (vers_can_native) diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index f1a98fd7291..8e3c8ff8d28 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1418,26 +1418,24 @@ row_insert_for_mysql( row_mysql_convert_row_to_innobase(node->row, prebuilt, mysql_rec, &blob_heap); - if (ins_mode != ROW_INS_NORMAL) - { + if (ins_mode != ROW_INS_NORMAL) { ut_ad(table->vers_start != table->vers_end); - /* Return back modified fields into mysql_rec, so that - upper logic may benefit from it (f.ex. 'on duplicate key'). */ - const mysql_row_templ_t* t = prebuilt->get_template_by_col(table->vers_end); + const mysql_row_templ_t* t + = prebuilt->get_template_by_col(table->vers_end); ut_ad(t); ut_ad(t->mysql_col_len == 8); if (ins_mode == ROW_INS_HISTORICAL) { - set_tuple_col_8(node->row, table->vers_end, trx->id, node->vers_end_buf); - } - else /* ROW_INS_VERSIONED */ { - set_tuple_col_8(node->row, table->vers_end, TRX_ID_MAX, node->vers_end_buf); - int8store(&mysql_rec[t->mysql_col_offset], TRX_ID_MAX); + set_tuple_col_8(node->row, table->vers_end, trx->id, + node->vers_end_buf); + } else /* ROW_INS_VERSIONED */ { + set_tuple_col_8(node->row, table->vers_end, TRX_ID_MAX, + node->vers_end_buf); t = prebuilt->get_template_by_col(table->vers_start); ut_ad(t); ut_ad(t->mysql_col_len == 8); - set_tuple_col_8(node->row, table->vers_start, trx->id, node->vers_start_buf); - int8store(&mysql_rec[t->mysql_col_offset], trx->id); + set_tuple_col_8(node->row, table->vers_start, trx->id, + node->vers_start_buf); } } diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index b4127d762b8..19b8d4b8f43 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -3476,9 +3476,11 @@ void upd_node_t::make_versioned_helper(const trx_t* trx, ulint idx) dict_index_t* clust_index = dict_table_get_first_index(table); + /* row_create_update_node_for_mysql() pre-allocated this much */ + ut_ad(update->n_fields < ulint(table->n_cols + table->n_v_cols)); + update->n_fields++; - upd_field_t* ufield = - upd_get_nth_field(update, upd_get_n_fields(update) - 1); + upd_field_t* ufield = upd_get_nth_field(update, update->n_fields - 1); const dict_col_t* col = dict_table_get_nth_col(table, idx); upd_field_set_field_no(ufield, dict_col_get_clust_pos(col, clust_index), diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index 5f91b9bcfd2..da0169e8a2b 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -806,12 +806,10 @@ void trx_rollback_recovered(bool all) trx_t *trx= trx_list.back(); trx_list.pop_back(); -#ifdef UNIV_DEBUG ut_ad(trx); - trx_mutex_enter(trx); + ut_d(trx_mutex_enter(trx)); ut_ad(trx->is_recovered && trx_state_eq(trx, TRX_STATE_ACTIVE)); - trx_mutex_exit(trx); -#endif + ut_d(trx_mutex_exit(trx)); if (!srv_is_being_started && !srv_undo_sources && srv_fast_shutdown) goto discard; diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index 63ca6f798e0..9809ed0a829 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -111,18 +111,9 @@ trx_rseg_clear_wsrep_checkpoint( - TRX_RSEG_WSREP_XID_INFO, 0, mtr); } -/** Update WSREP checkpoint XID in first rollback segment header -as part of wsrep_set_SE_checkpoint() when it is guaranteed that there -are no wsrep transactions committing. -If the UUID part of the WSREP XID does not match to the UUIDs of XIDs already -stored into rollback segments, the WSREP XID in all the remaining rollback -segments will be reset. -@param[in] xid WSREP XID */ -void trx_rseg_update_wsrep_checkpoint(const XID* xid) +static void +trx_rseg_update_wsrep_checkpoint(const XID* xid, mtr_t* mtr) { - mtr_t mtr; - mtr.start(); - const byte* xid_uuid = wsrep_xid_uuid(xid); /* We must make check against wsrep_uuid here, the trx_rseg_update_wsrep_checkpoint() writes over wsrep_uuid with @@ -133,12 +124,12 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) const trx_rseg_t* rseg = trx_sys.rseg_array[0]; trx_rsegf_t* rseg_header = trx_rsegf_get(rseg->space, rseg->page_no, - &mtr); + mtr); if (UNIV_UNLIKELY(mach_read_from_4(rseg_header + TRX_RSEG_FORMAT))) { - trx_rseg_format_upgrade(rseg_header, &mtr); + trx_rseg_format_upgrade(rseg_header, mtr); } - trx_rseg_update_wsrep_checkpoint(rseg_header, xid, &mtr); + trx_rseg_update_wsrep_checkpoint(rseg_header, xid, mtr); if (must_clear_rsegs) { /* Because the UUID part of the WSREP XID differed @@ -150,13 +141,25 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) trx_sys.rseg_array[rseg_id]) { trx_rseg_clear_wsrep_checkpoint( trx_rsegf_get(rseg->space, - rseg->page_no, - &mtr), - &mtr); + rseg->page_no, mtr), + mtr); } } } +} +/** Update WSREP checkpoint XID in first rollback segment header +as part of wsrep_set_SE_checkpoint() when it is guaranteed that there +are no wsrep transactions committing. +If the UUID part of the WSREP XID does not match to the UUIDs of XIDs already +stored into rollback segments, the WSREP XID in all the remaining rollback +segments will be reset. +@param[in] xid WSREP XID */ +void trx_rseg_update_wsrep_checkpoint(const XID* xid) +{ + mtr_t mtr; + mtr.start(); + trx_rseg_update_wsrep_checkpoint(xid, &mtr); mtr.commit(); } @@ -232,16 +235,6 @@ bool trx_rseg_read_wsrep_checkpoint(XID& xid) rseg_id++, mtr.commit()) { mtr.start(); const buf_block_t* sys = trx_sysf_get(&mtr, false); - if (rseg_id == 0) { - found = trx_rseg_init_wsrep_xid(sys->frame, xid); - ut_ad(!found || xid.formatID == 1); - if (found) { - max_xid_seqno = wsrep_xid_seqno(&xid); - memcpy(wsrep_uuid, wsrep_xid_uuid(&xid), - sizeof wsrep_uuid); - } - } - const uint32_t page_no = trx_sysf_rseg_get_page_no( sys, rseg_id); @@ -566,6 +559,9 @@ trx_rseg_array_init() trx_sys.recovered_binlog_offset = 0; #ifdef WITH_WSREP trx_sys.recovered_wsrep_xid.null(); + XID wsrep_sys_xid; + wsrep_sys_xid.null(); + bool wsrep_xid_in_rseg_found = false; #endif for (ulint rseg_id = 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) { @@ -580,6 +576,9 @@ trx_rseg_array_init() TRX_SYS + TRX_SYS_TRX_ID_STORE + sys->frame); trx_rseg_init_binlog_info(sys->frame); +#ifdef WITH_WSREP + wsrep_sys_xid.set(&trx_sys.recovered_wsrep_xid); +#endif } const uint32_t page_no = trx_sysf_rseg_get_page_no( @@ -595,12 +594,49 @@ trx_rseg_array_init() ut_ad(!trx_sys.rseg_array[rseg_id]); trx_sys.rseg_array[rseg_id] = rseg; trx_rseg_mem_restore(rseg, max_trx_id, &mtr); +#ifdef WITH_WSREP + if (!wsrep_sys_xid.is_null() && + !wsrep_sys_xid.eq(&trx_sys.recovered_wsrep_xid)) { + wsrep_xid_in_rseg_found = true; + ut_ad(memcmp(wsrep_xid_uuid(&wsrep_sys_xid), + wsrep_xid_uuid(&trx_sys.recovered_wsrep_xid), + sizeof wsrep_uuid) + || wsrep_xid_seqno( + &wsrep_sys_xid) + <= wsrep_xid_seqno( + &trx_sys.recovered_wsrep_xid)); + } +#endif } } mtr.commit(); } +#ifdef WITH_WSREP + if (!wsrep_sys_xid.is_null()) { + /* Upgrade from a version prior to 10.3.5, + where WSREP XID was stored in TRX_SYS page. + If no rollback segment has a WSREP XID set, + we must copy the XID found in TRX_SYS page + to rollback segments. */ + mtr_t mtr; + mtr.start(); + + if (!wsrep_xid_in_rseg_found) { + trx_rseg_update_wsrep_checkpoint(&wsrep_sys_xid, &mtr); + } + + /* Finally, clear WSREP XID in TRX_SYS page. */ + const buf_block_t* sys = trx_sysf_get(&mtr); + mlog_write_ulint(TRX_SYS + TRX_SYS_WSREP_XID_INFO + + + TRX_SYS_WSREP_XID_MAGIC_N_FLD + sys->frame, + 0, MLOG_4BYTES, &mtr); + + mtr.commit(); + } +#endif + trx_sys.init_max_trx_id(max_trx_id + 1); }