Merge 10.3 into 10.4
This commit is contained in:
commit
cf77951fb6
@ -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);
|
||||
|
@ -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 #
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user