Skip to content

Commit f99abb4

Browse files
committed
MDEV-17573 Assertion in federatedx on multi-update
Cause: shared federatedx_io cannot store table-specific data. Fix: move current row reference `federatedx_io_mysql::current` to ha_federatedx. FederatedX connection (represented by federatedx_io) is stored into federatedx_txn::txn_list of per-server connections (see federatedx_txn::acquire()). federatedx_txn object is stored into THD (see ha_federatedx::external_lock()). When multiple handlers acquire FederatedX connection they get single federatedx_io instance. Multiple handlers do their operation via federatedx_io_mysql::mark_position() and federatedx_io_mysql::fetch_row() in arbitrarty manner. They access the same federatedx_io_mysql instance and same MYSQL_ROWS *current pointer, so one handler disrupts the work of the other. Related to "MDEV-14551 Can't find record in table on multi-table update with ORDER BY".
1 parent a3f7f23 commit f99abb4

File tree

6 files changed

+77
-15
lines changed

6 files changed

+77
-15
lines changed

mysql-test/suite/federated/federatedx.result

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2283,6 +2283,32 @@ connection default;
22832283
connection master;
22842284
CREATE TABLE t1 (a INT) ENGINE=FEDERATED CONNECTION='mysql://@127.0.0.1:SLAVE_PORT/federated/t1';
22852285
ERROR HY000: Can't create federated table. Foreign data src error: database: 'federated' username: '' hostname: '127.0.0.1'
2286+
#
2287+
# MDEV-17573 Assertion in federatedx on multi-update
2288+
#
2289+
create table t1 (
2290+
x int,
2291+
d datetime);
2292+
create table t1f engine=FEDERATED connection='mysql://root@127.0.0.1:MASTER_MYPORT/test/t1';
2293+
create table t2 (
2294+
x int, y int,
2295+
d datetime);
2296+
create table t2f engine=FEDERATED connection='mysql://root@127.0.0.1:MASTER_MYPORT/test/t2';
2297+
create table t3 (
2298+
x int, y int, z int,
2299+
d datetime);
2300+
create table t3f engine=FEDERATED connection='mysql://root@127.0.0.1:MASTER_MYPORT/test/t3';
2301+
insert into t1 values (1, "1990-01-01 00:00");
2302+
insert into t1 values (1, "1991-01-01 11:11");
2303+
insert into t2 values (2, 2, "1992-02-02 22:22");
2304+
insert into t3 values (3, 3, 3, "1993-03-03 23:33");
2305+
update t1f, t2f, t3f set t1f.x= 11, t2f.y= 22, t3f.z= 33;
2306+
drop table t1f;
2307+
drop table t2f;
2308+
drop table t3f;
2309+
drop table t1;
2310+
drop table t2;
2311+
drop table t3;
22862312
connection master;
22872313
DROP TABLE IF EXISTS federated.t1;
22882314
DROP DATABASE IF EXISTS federated;

mysql-test/suite/federated/federatedx.test

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,4 +2010,33 @@ connection master;
20102010
--error ER_CANT_CREATE_FEDERATED_TABLE
20112011
eval CREATE TABLE t1 (a INT) ENGINE=FEDERATED CONNECTION='mysql://@127.0.0.1:$SLAVE_MYPORT/federated/t1';
20122012

2013+
--echo #
2014+
--echo # MDEV-17573 Assertion in federatedx on multi-update
2015+
--echo #
2016+
create table t1 (
2017+
x int,
2018+
d datetime);
2019+
--replace_result $MASTER_MYPORT MASTER_MYPORT
2020+
eval create table t1f engine=FEDERATED connection='mysql://root@127.0.0.1:$MASTER_MYPORT/test/t1';
2021+
2022+
create table t2 (
2023+
x int, y int,
2024+
d datetime);
2025+
--replace_result $MASTER_MYPORT MASTER_MYPORT
2026+
eval create table t2f engine=FEDERATED connection='mysql://root@127.0.0.1:$MASTER_MYPORT/test/t2';
2027+
2028+
create table t3 (
2029+
x int, y int, z int,
2030+
d datetime);
2031+
--replace_result $MASTER_MYPORT MASTER_MYPORT
2032+
eval create table t3f engine=FEDERATED connection='mysql://root@127.0.0.1:$MASTER_MYPORT/test/t3';
2033+
2034+
insert into t1 values (1, "1990-01-01 00:00");
2035+
insert into t1 values (1, "1991-01-01 11:11");
2036+
insert into t2 values (2, 2, "1992-02-02 22:22");
2037+
insert into t3 values (3, 3, 3, "1993-03-03 23:33");
2038+
update t1f, t2f, t3f set t1f.x= 11, t2f.y= 22, t3f.z= 33;
2039+
2040+
drop table t1f; drop table t2f; drop table t3f; drop table t1; drop table t2; drop table t3;
2041+
20132042
source include/federated_cleanup.inc;

storage/federatedx/federatedx_io_mysql.cc

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ struct mysql_position
6464
class federatedx_io_mysql :public federatedx_io
6565
{
6666
MYSQL mysql; /* MySQL connection */
67-
MYSQL_ROWS *current;
6867
DYNAMIC_ARRAY savepoints;
6968
bool requested_autocommit;
7069
bool actual_autocommit;
@@ -108,7 +107,8 @@ class federatedx_io_mysql :public federatedx_io
108107
virtual void free_result(FEDERATEDX_IO_RESULT *io_result);
109108
virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result);
110109
virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result);
111-
virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result);
110+
virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result,
111+
FEDERATEDX_IO_ROWS **current= NULL);
112112
virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result);
113113
virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
114114
unsigned int column);
@@ -117,7 +117,7 @@ class federatedx_io_mysql :public federatedx_io
117117

118118
virtual size_t get_ref_length() const;
119119
virtual void mark_position(FEDERATEDX_IO_RESULT *io_result,
120-
void *ref);
120+
void *ref, FEDERATEDX_IO_ROWS *current);
121121
virtual int seek_position(FEDERATEDX_IO_RESULT **io_result,
122122
const void *ref);
123123
virtual void set_thd(void *thd);
@@ -515,10 +515,12 @@ my_ulonglong federatedx_io_mysql::get_num_rows(FEDERATEDX_IO_RESULT *io_result)
515515
}
516516

517517

518-
FEDERATEDX_IO_ROW *federatedx_io_mysql::fetch_row(FEDERATEDX_IO_RESULT *io_result)
518+
FEDERATEDX_IO_ROW *federatedx_io_mysql::fetch_row(FEDERATEDX_IO_RESULT *io_result,
519+
FEDERATEDX_IO_ROWS **current)
519520
{
520521
MYSQL_RES *result= (MYSQL_RES*)io_result;
521-
current= result->data_cursor;
522+
if (current)
523+
*current= (FEDERATEDX_IO_ROWS *) result->data_cursor;
522524
return (FEDERATEDX_IO_ROW *) mysql_fetch_row(result);
523525
}
524526

@@ -626,11 +628,11 @@ size_t federatedx_io_mysql::get_ref_length() const
626628

627629

628630
void federatedx_io_mysql::mark_position(FEDERATEDX_IO_RESULT *io_result,
629-
void *ref)
631+
void *ref, FEDERATEDX_IO_ROWS *current)
630632
{
631633
mysql_position& pos= *reinterpret_cast<mysql_position*>(ref);
632634
pos.result= (MYSQL_RES *) io_result;
633-
pos.offset= current;
635+
pos.offset= (MYSQL_ROW_OFFSET) current;
634636
}
635637

636638
int federatedx_io_mysql::seek_position(FEDERATEDX_IO_RESULT **io_result,

storage/federatedx/federatedx_io_null.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,16 @@ class federatedx_io_null :public federatedx_io
9090
virtual void free_result(FEDERATEDX_IO_RESULT *io_result);
9191
virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result);
9292
virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result);
93-
virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result);
93+
virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result,
94+
FEDERATEDX_IO_ROWS **current= NULL);
9495
virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result);
9596
virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
9697
unsigned int column);
9798
virtual bool is_column_null(const FEDERATEDX_IO_ROW *row,
9899
unsigned int column) const;
99100
virtual size_t get_ref_length() const;
100101
virtual void mark_position(FEDERATEDX_IO_RESULT *io_result,
101-
void *ref);
102+
void *ref, FEDERATEDX_IO_ROWS *current);
102103
virtual int seek_position(FEDERATEDX_IO_RESULT **io_result,
103104
const void *ref);
104105
};
@@ -242,7 +243,8 @@ my_ulonglong federatedx_io_null::get_num_rows(FEDERATEDX_IO_RESULT *)
242243
}
243244

244245

245-
FEDERATEDX_IO_ROW *federatedx_io_null::fetch_row(FEDERATEDX_IO_RESULT *)
246+
FEDERATEDX_IO_ROW *federatedx_io_null::fetch_row(FEDERATEDX_IO_RESULT *,
247+
FEDERATEDX_IO_ROWS **current)
246248
{
247249
return NULL;
248250
}
@@ -288,7 +290,7 @@ size_t federatedx_io_null::get_ref_length() const
288290

289291

290292
void federatedx_io_null::mark_position(FEDERATEDX_IO_RESULT *io_result,
291-
void *ref)
293+
void *ref, FEDERATEDX_IO_ROWS *current)
292294
{
293295
}
294296

storage/federatedx/ha_federatedx.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2908,7 +2908,7 @@ int ha_federatedx::read_next(uchar *buf, FEDERATEDX_IO_RESULT *result)
29082908
DBUG_RETURN(retval);
29092909

29102910
/* Fetch a row, insert it back in a row format. */
2911-
if (!(row= io->fetch_row(result)))
2911+
if (!(row= io->fetch_row(result, &current)))
29122912
DBUG_RETURN(HA_ERR_END_OF_FILE);
29132913

29142914
if (!(retval= convert_row_to_internal_format(buf, row, result)))
@@ -2952,7 +2952,7 @@ void ha_federatedx::position(const uchar *record __attribute__ ((unused)))
29522952
if (txn->acquire(share, ha_thd(), TRUE, &io))
29532953
DBUG_VOID_RETURN;
29542954

2955-
io->mark_position(stored_result, ref);
2955+
io->mark_position(stored_result, ref, current);
29562956

29572957
position_called= TRUE;
29582958

storage/federatedx/ha_federatedx.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ typedef struct st_federatedx_share {
129129

130130
typedef struct st_federatedx_result FEDERATEDX_IO_RESULT;
131131
typedef struct st_federatedx_row FEDERATEDX_IO_ROW;
132+
typedef struct st_federatedx_rows FEDERATEDX_IO_ROWS;
132133
typedef ptrdiff_t FEDERATEDX_IO_OFFSET;
133134

134135
class federatedx_io
@@ -203,7 +204,8 @@ class federatedx_io
203204
virtual void free_result(FEDERATEDX_IO_RESULT *io_result)=0;
204205
virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result)=0;
205206
virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result)=0;
206-
virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result)=0;
207+
virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result,
208+
FEDERATEDX_IO_ROWS **current= NULL)=0;
207209
virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result)=0;
208210
virtual const char *get_column_data(FEDERATEDX_IO_ROW *row,
209211
unsigned int column)=0;
@@ -212,7 +214,7 @@ class federatedx_io
212214

213215
virtual size_t get_ref_length() const=0;
214216
virtual void mark_position(FEDERATEDX_IO_RESULT *io_result,
215-
void *ref)=0;
217+
void *ref, FEDERATEDX_IO_ROWS *current)=0;
216218
virtual int seek_position(FEDERATEDX_IO_RESULT **io_result,
217219
const void *ref)=0;
218220
virtual void set_thd(void *thd) { }
@@ -265,6 +267,7 @@ class ha_federatedx: public handler
265267
federatedx_txn *txn;
266268
federatedx_io *io;
267269
FEDERATEDX_IO_RESULT *stored_result;
270+
FEDERATEDX_IO_ROWS *current;
268271
/**
269272
Array of all stored results we get during a query execution.
270273
*/

0 commit comments

Comments
 (0)