Skip to content

Commit

Permalink
Merge 10.2 into 10.3
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-m committed Mar 19, 2019
2 parents 26e5bff + a77e266 commit 117291d
Show file tree
Hide file tree
Showing 20 changed files with 409 additions and 164 deletions.
6 changes: 6 additions & 0 deletions include/mysql/service_wsrep.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ extern struct wsrep_service_st {
long long (*wsrep_thd_trx_seqno_func)(THD *thd);
struct wsrep_ws_handle * (*wsrep_thd_ws_handle_func)(THD *thd);
void (*wsrep_thd_auto_increment_variables_func)(THD *thd, unsigned long long *offset, unsigned long long *increment);
void (*wsrep_set_load_multi_commit_func)(THD *thd, bool split);
bool (*wsrep_is_load_multi_commit_func)(THD *thd);
int (*wsrep_trx_is_aborting_func)(MYSQL_THD thd);
int (*wsrep_trx_order_before_func)(MYSQL_THD, MYSQL_THD);
void (*wsrep_unlock_rollback_func)();
Expand Down Expand Up @@ -156,6 +158,8 @@ extern struct wsrep_service_st {
#define wsrep_thd_trx_seqno(T) wsrep_service->wsrep_thd_trx_seqno_func(T)
#define wsrep_thd_ws_handle(T) wsrep_service->wsrep_thd_ws_handle_func(T)
#define wsrep_thd_auto_increment_variables(T,O,I) wsrep_service->wsrep_thd_auto_increment_variables_func(T,O,I)
#define wsrep_set_load_multi_commit(T,S) wsrep_service->wsrep_set_load_multi_commit_func(T,S)
#define wsrep_is_load_multi_commit(T) wsrep_service->wsrep_is_load_multi_commit_func(T)
#define wsrep_trx_is_aborting(T) wsrep_service->wsrep_trx_is_aborting_func(T)
#define wsrep_trx_order_before(T1,T2) wsrep_service->wsrep_trx_order_before_func(T1,T2)
#define wsrep_unlock_rollback() wsrep_service->wsrep_unlock_rollback_func()
Expand Down Expand Up @@ -212,6 +216,8 @@ my_bool wsrep_thd_is_wsrep(MYSQL_THD thd);
struct wsrep *get_wsrep();
struct wsrep_ws_handle *wsrep_thd_ws_handle(THD *thd);
void wsrep_thd_auto_increment_variables(THD *thd, unsigned long long *offset, unsigned long long *increment);
void wsrep_set_load_multi_commit(THD *thd, bool split);
bool wsrep_is_load_multi_commit(THD *thd);
void wsrep_aborting_thd_enqueue(THD *thd);
void wsrep_lock_rollback();
void wsrep_post_commit(THD* thd, bool all);
Expand Down
13 changes: 13 additions & 0 deletions mysql-test/main/update.result
Original file line number Diff line number Diff line change
Expand Up @@ -719,3 +719,16 @@ Handler_read_rnd_deleted 0
Handler_read_rnd_next 0
drop table t1, t2;
# End of MariaDB 10.0 tests
#
# MDEV-18945: multi-table update with constant table and
# comparison of date field with integer field
#
CREATE TABLE t1 (i1 int, d1 date , i2 int , d2 date) engine=myisam;
INSERT INTO t1 VALUES (19,'0000-00-00',73,'2008-05-21');
CREATE TABLE t2 (d1 date , i1 int, i2 int , d2 date) engine=myisam;
INSERT INTO t2 VALUES
('2006-01-12',-102,45,'2023-11-25'),('2034-12-19',-102,45,'2001-11-20');
UPDATE t1,t2 SET t1.i1 = -39 WHERE t2.d1 <> t1.i1 AND t2.d1 = t1.d2;
ERROR 22007: Incorrect datetime value: '19' for column `test`.`t1`.`i1` at row 1
DROP TABLE t1,t2;
# End of MariaDB 10.2 tests
19 changes: 19 additions & 0 deletions mysql-test/main/update.test
Original file line number Diff line number Diff line change
Expand Up @@ -654,3 +654,22 @@ show status like 'Handler_read%';
drop table t1, t2;

--echo # End of MariaDB 10.0 tests

--echo #
--echo # MDEV-18945: multi-table update with constant table and
--echo # comparison of date field with integer field
--echo #

CREATE TABLE t1 (i1 int, d1 date , i2 int , d2 date) engine=myisam;
INSERT INTO t1 VALUES (19,'0000-00-00',73,'2008-05-21');

CREATE TABLE t2 (d1 date , i1 int, i2 int , d2 date) engine=myisam;
INSERT INTO t2 VALUES
('2006-01-12',-102,45,'2023-11-25'),('2034-12-19',-102,45,'2001-11-20');

--error ER_TRUNCATED_WRONG_VALUE
UPDATE t1,t2 SET t1.i1 = -39 WHERE t2.d1 <> t1.i1 AND t2.d1 = t1.d2;

DROP TABLE t1,t2;

--echo # End of MariaDB 10.2 tests
3 changes: 3 additions & 0 deletions mysql-test/suite/galera/r/galera_kill_largechanges.result
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
connection node_1;
connection node_2;
connection node_1;
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
CREATE TABLE ten (f1 INTEGER) ENGINE=InnoDB;
INSERT INTO ten VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10),(11);
Expand All @@ -15,5 +17,6 @@ COUNT(*)
SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
VARIABLE_VALUE
2
connection node_1;
DROP TABLE t1;
DROP TABLE ten;
36 changes: 36 additions & 0 deletions mysql-test/suite/galera_3nodes/r/galera_load_data_ist.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
connection node_1;
connection node_2;
connection node_3;
connection node_1;
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;
connection node_2;
connection node_3;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1';
SET SESSION wsrep_on = OFF;
SET SESSION wsrep_on = ON;
SET SESSION wsrep_sync_wait = 0;
connection node_2a;
SET SESSION wsrep_sync_wait = 0;
connection node_2;
SET GLOBAL wsrep_load_data_splitting = TRUE;
SET DEBUG_SYNC='intermediate_transaction_commit SIGNAL commited WAIT_FOR ist';
connection node_2a;
SET DEBUG_SYNC='now WAIT_FOR commited';
connection node_3;
SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0';
connection node_2a;
SET DEBUG_SYNC='now SIGNAL ist';
connection node_1;
connection node_2;
SET DEBUG_SYNC='RESET';
SELECT COUNT(*) = 95000 FROM t1;
COUNT(*) = 95000
1
wsrep_last_committed_diff
1
connection node_1;
SET GLOBAL wsrep_load_data_splitting = 1;;
DROP TABLE t1;
disconnect node_3;
disconnect node_2;
disconnect node_1;
4 changes: 4 additions & 0 deletions mysql-test/suite/galera_3nodes/t/galera_load_data_ist.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
!include ../galera_3nodes.cnf

[mysqld]
wsrep-causal-reads=OFF
124 changes: 124 additions & 0 deletions mysql-test/suite/galera_3nodes/t/galera_load_data_ist.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
--source include/have_debug_sync.inc
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/big_test.inc

# Establish connection to the third node:
--let $galera_connection_name = node_3
--let $galera_server_number = 3
--source include/galera_connect.inc

# Establish additional connection to the second node
# (which is used in the test for synchronization control):
--let $galera_connection_name = node_2a
--let $galera_server_number = 2
--source include/galera_connect.inc

# Save original auto_increment_offset values:
--let $node_1=node_1
--let $node_2=node_2
--let $node_3=node_3
--source ../galera/include/auto_increment_offset_save.inc

# Create a file for LOAD DATA with 95K entries
--connection node_1
--perl
open(FILE, ">", "$ENV{'MYSQLTEST_VARDIR'}/tmp/galera_var_load_data_splitting.csv") or die;
foreach my $i (1..95000) {
print FILE "$i\n";
}
EOF

CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB;

# Let's wait for the completion of the formation of a cluster
# of three nodes:
--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
--connection node_2
--source include/wait_until_ready.inc
--connection node_3
--source include/wait_until_ready.inc

# Disconnect the third node from the cluster:
SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 1';
SET SESSION wsrep_on = OFF;
--let $wait_condition = SELECT VARIABLE_VALUE = 'non-Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
--source include/wait_condition.inc
SET SESSION wsrep_on = ON;
SET SESSION wsrep_sync_wait = 0;

# Disable sync wait for control connection:
--connection node_2a
SET SESSION wsrep_sync_wait = 0;

# Let's wait until the other nodes stop seeing the third
# node in the cluster:
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc

# Record wsrep_last_committed as it was before LOAD DATA:
--connection node_2
--let $wsrep_last_committed_before = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`

# Enable splitting for LOAD DATA:
--let $wsrep_load_data_splitting_orig = `SELECT @@wsrep_load_data_splitting`
SET GLOBAL wsrep_load_data_splitting = TRUE;

# Stop after the first commit and wait for the IST signal:
SET DEBUG_SYNC='intermediate_transaction_commit SIGNAL commited WAIT_FOR ist';

# Perform the LOAD DATA statement:
--disable_query_log
let v1='$MYSQLTEST_VARDIR/tmp/galera_var_load_data_splitting.csv';
--send_eval LOAD DATA INFILE $v1 INTO TABLE t1;
--enable_query_log

# Wait for the first commit:
--connection node_2a
SET DEBUG_SYNC='now WAIT_FOR commited';

# Initiate the IST:
--connection node_3
SET GLOBAL wsrep_provider_options = 'gmcast.isolate = 0';

# Continue the execution of LOAD DATA:
--connection node_2a
SET DEBUG_SYNC='now SIGNAL ist';

# Let's wait for the recovery of the cluster
# of three nodes:
--connection node_1
--let $wait_condition = SELECT VARIABLE_VALUE = 3 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc

# Save the LOAD DATA results:
--connection node_2
--reap

# Reset all synchronization points and signals:
SET DEBUG_SYNC='RESET';

# Read the wsrep_last_commited after LOAD DATA:
--let $wsrep_last_committed_after = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME = 'wsrep_last_committed'`

# Check the records:
SELECT COUNT(*) = 95000 FROM t1;

# LOAD-ing 95K rows should causes 10 commits to be registered:
--disable_query_log
--eval SELECT $wsrep_last_committed_after = $wsrep_last_committed_before + 10 AS wsrep_last_committed_diff;
--enable_query_log

# Restore the original splitting:
--connection node_1
--eval SET GLOBAL wsrep_load_data_splitting = $wsrep_load_data_splitting_orig;

# Drop test table:
DROP TABLE t1;

# Restore original auto_increment_offset values:
--source ../galera/include/auto_increment_offset_restore.inc

--let $galera_cluster_size=3
--source include/galera_end.inc
51 changes: 51 additions & 0 deletions sql/log.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6474,8 +6474,25 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate)
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 */
}
}
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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))
{
/*
Expand All @@ -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);
}
Expand Down
2 changes: 2 additions & 0 deletions sql/sql_class.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions sql/sql_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -4727,6 +4727,14 @@ class THD :public Statement,
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 */
Expand Down
Loading

0 comments on commit 117291d

Please sign in to comment.