From 7971360ffa00e6a024182b1d437a50d174eb4b37 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 2 Nov 2016 21:08:44 -0400 Subject: [PATCH 01/11] Fix a build failure noticed on Yakkety. --- storage/innobase/handler/ha_innodb.h | 4 ++-- storage/xtradb/handler/ha_innodb.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index adaad543dd1..eea1a1f7cff 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -467,8 +467,8 @@ extern "C" void wsrep_thd_set_conflict_state( extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); -extern "C"void wsrep_thd_LOCK(THD *thd); -extern "C"void wsrep_thd_UNLOCK(THD *thd); +extern "C" void wsrep_thd_LOCK(THD *thd); +extern "C" void wsrep_thd_UNLOCK(THD *thd); extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); extern "C" time_t wsrep_thd_query_start(THD *thd); extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index cb7dd6b9cf4..a824f4c680a 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -482,8 +482,8 @@ extern "C" void wsrep_thd_set_conflict_state( extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); -extern "C"void wsrep_thd_LOCK(THD *thd); -extern "C"void wsrep_thd_UNLOCK(THD *thd); +extern "C" void wsrep_thd_LOCK(THD *thd); +extern "C" void wsrep_thd_UNLOCK(THD *thd); extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); extern "C" time_t wsrep_thd_query_start(THD *thd); extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); From c7e1c89070e34e13cb4a3e947021b91fb211959a Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Wed, 2 Nov 2016 21:10:39 -0400 Subject: [PATCH 02/11] Disable unstable galera_concurrent_ctas test. --- mysql-test/suite/galera/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 771053778d3..907f7931483 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -29,5 +29,6 @@ galera_transaction_read_only : mysql-wsrep/issues/229 galera_gcs_fragment : Incorrect arguments to SET galera_flush_local : Fails sporadically galera_binlog_stmt_autoinc : TODO: investigate +galera_concurrent_ctas : Test times out, investigate galera_sst_xtrabackup-v2-options : TODO: Fix test case mysql-wsrep#33 : TODO: investigate From 41e11a8ac6ae62a9320beff451dbd031540c1f7a Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Mon, 7 Nov 2016 10:25:03 -0500 Subject: [PATCH 03/11] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a82a4e4d77d..36834bdb92d 100644 --- a/VERSION +++ b/VERSION @@ -1,3 +1,3 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=0 -MYSQL_VERSION_PATCH=28 +MYSQL_VERSION_PATCH=29 From 52ea5ad865b4f6b4b37176296a3be0a716c5109a Mon Sep 17 00:00:00 2001 From: SachinSetiya Date: Thu, 1 Dec 2016 11:24:04 +0530 Subject: [PATCH 04/11] MDEV-11016 wsrep_node_is_ready() check is too strict Problem:- The condition that checks for node readiness is too strict as it does not allow SELECTs even if these selects do not access any tables. For example,if we run SELECT 1; OR SELECT @@max_allowed_packet; Solution:- We need not to report this error when all_tables(lex->query_tables) is NULL: --- .../suite/galera/r/galera_var_dirty_reads.result | 13 +++++++++++++ .../suite/galera/t/galera_var_dirty_reads.test | 7 +++++++ sql/sql_parse.cc | 4 ++++ 3 files changed, 24 insertions(+) diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result index 6d703c8cf95..6a2aa1eb5e7 100644 --- a/mysql-test/suite/galera/r/galera_var_dirty_reads.result +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -18,6 +18,19 @@ SET @@session.wsrep_dirty_reads=ON; SELECT * FROM t1; i 1 +SET @@session.wsrep_dirty_reads=OFF; +SELECT 2; +2 +2 +SELECT @@max_allowed_packet; +@@max_allowed_packet +4194304 +SELECT 2+2 from DUAL; +2+2 +4 +SELECT sysdate() from DUAL; +sysdate() +2016-10-28 23:13:06 SELECT * FROM t1; i 1 diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test index dfd8d5ecf29..0c81779ca65 100644 --- a/mysql-test/suite/galera/t/galera_var_dirty_reads.test +++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test @@ -36,6 +36,13 @@ SET @@session.wsrep_dirty_reads=ON; SELECT * FROM t1; +#Select query which does not access table should be allowed MDEV-11016 +SET @@session.wsrep_dirty_reads=OFF; +SELECT 2; +SELECT @@max_allowed_packet; +SELECT 2+2 from DUAL; +SELECT sysdate() from DUAL; + --disable_query_log --eval SET @@global.wsrep_cluster_address = '$wsrep_cluster_address_saved' --enable_query_log diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4ed1b7a5323..11613fac026 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2635,11 +2635,15 @@ mysql_execute_command(THD *thd) /* Bail out if DB snapshot has not been installed. We however, allow SET and SHOW queries. + SHOW and SELECT queries (only if wsrep_dirty_reads is set or when it + does not access ant table) */ if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && lex->sql_command != SQLCOM_SET_OPTION && !(thd->variables.wsrep_dirty_reads && lex->sql_command == SQLCOM_SELECT) && + !(lex->sql_command == SQLCOM_SELECT && + !all_table) && !wsrep_is_show_query(lex->sql_command)) { my_message(ER_UNKNOWN_COM_ERROR, From 55b4579633ec81481823b3dfaa45674db6416a50 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Mon, 5 Dec 2016 16:28:29 -0500 Subject: [PATCH 05/11] Fix build failure. --- sql/sql_parse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 11613fac026..53350751d79 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2643,7 +2643,7 @@ mysql_execute_command(THD *thd) !(thd->variables.wsrep_dirty_reads && lex->sql_command == SQLCOM_SELECT) && !(lex->sql_command == SQLCOM_SELECT && - !all_table) && + !all_tables) && !wsrep_is_show_query(lex->sql_command)) { my_message(ER_UNKNOWN_COM_ERROR, From e156ea1b9517dd155f68f8d683704ecf5370346a Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 9 Dec 2016 12:15:41 -0500 Subject: [PATCH 06/11] Fix failing tests. --- .../suite/galera/r/galera_split_brain.result | 1 - .../r/galera_var_cluster_address.result | 36 ++++------ .../galera/r/galera_var_dirty_reads.result | 15 ++-- mysql-test/suite/galera/suite.pm | 1 + .../suite/galera/t/galera_split_brain.test | 5 +- .../galera/t/galera_var_cluster_address.test | 72 +++++++------------ .../galera/t/galera_var_dirty_reads.test | 12 +++- 7 files changed, 59 insertions(+), 83 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_split_brain.result b/mysql-test/suite/galera/r/galera_split_brain.result index 615615040fe..6473f95735b 100644 --- a/mysql-test/suite/galera/r/galera_split_brain.result +++ b/mysql-test/suite/galera/r/galera_split_brain.result @@ -2,4 +2,3 @@ call mtr.add_suppression("WSREP: TO isolation failed for: "); Killing server ... CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -SET GLOBAL wsrep_cluster_address = ''; diff --git a/mysql-test/suite/galera/r/galera_var_cluster_address.result b/mysql-test/suite/galera/r/galera_var_cluster_address.result index f8bd869f8fe..17b5a7bca37 100644 --- a/mysql-test/suite/galera/r/galera_var_cluster_address.result +++ b/mysql-test/suite/galera/r/galera_var_cluster_address.result @@ -1,6 +1,6 @@ SET GLOBAL wsrep_cluster_address = 'foo://'; SET SESSION wsrep_sync_wait=0; -SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS; +SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS; ERROR 08S01: WSREP has not yet prepared node for application use SHOW STATUS LIKE 'wsrep_ready'; Variable_name Value @@ -20,32 +20,20 @@ VARIABLE_VALUE = 1 SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; VARIABLE_VALUE = 'Primary' 1 -SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; -SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; -VARIABLE_VALUE = 'Primary' -1 -SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -VARIABLE_VALUE = 2 -1 -SET GLOBAL wsrep_cluster_address = 'gcomm://192.0.2.1'; -SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS; -ERROR 08S01: WSREP has not yet prepared node for application use -SHOW STATUS LIKE 'wsrep_ready'; -Variable_name Value -wsrep_ready OFF -SHOW STATUS LIKE 'wsrep_cluster_status'; -Variable_name Value -wsrep_cluster_status non-Primary -SHOW STATUS LIKE 'wsrep_local_state'; -Variable_name Value -wsrep_local_state 0 -SHOW STATUS LIKE 'wsrep_local_state_comment'; -Variable_name Value -wsrep_local_state_comment Initialized -SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; VARIABLE_VALUE = 'Primary' 1 SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; VARIABLE_VALUE = 2 1 +CALL mtr.add_suppression("Backend not supported: foo"); +CALL mtr.add_suppression("Failed to initialize backend using 'foo"); +CALL mtr.add_suppression("Failed to open channel 'my_wsrep_cluster' at 'foo"); +CALL mtr.add_suppression("gcs connect failed: Socket type not supported"); +CALL mtr.add_suppression("wsrep::connect\\(\\) failed: 7"); +CALL mtr.add_suppression("gcs_caused\\(\\) returned -103 \\(Software caused connection abort\\)"); +CALL mtr.add_suppression("failed to open gcomm backend connection: 110: failed to reach primary view: 110"); +CALL mtr.add_suppression("Failed to open backend connection: -110 \\(Connection timed out\\)"); +CALL mtr.add_suppression("gcs connect failed: Connection timed out"); +CALL mtr.add_suppression("WSREP: wsrep::connect\\(foo://\\) failed: 7"); +# End of test diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result index 6a2aa1eb5e7..c0ffb2d4860 100644 --- a/mysql-test/suite/galera/r/galera_var_dirty_reads.result +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -18,19 +18,22 @@ SET @@session.wsrep_dirty_reads=ON; SELECT * FROM t1; i 1 +# +# MDEV-11016: wsrep_node_is_ready() check is too strict +# SET @@session.wsrep_dirty_reads=OFF; SELECT 2; 2 2 -SELECT @@max_allowed_packet; -@@max_allowed_packet -4194304 SELECT 2+2 from DUAL; 2+2 4 -SELECT sysdate() from DUAL; -sysdate() -2016-10-28 23:13:06 +SET @VAR=1; +SELECT @VAR; +@VAR +1 +SELECT @@max_allowed_packet; +SELECT SYSDATE() from DUAL; SELECT * FROM t1; i 1 diff --git a/mysql-test/suite/galera/suite.pm b/mysql-test/suite/galera/suite.pm index d6cd4273014..5b69ff26615 100644 --- a/mysql-test/suite/galera/suite.pm +++ b/mysql-test/suite/galera/suite.pm @@ -68,6 +68,7 @@ push @::global_suppressions, qr|WSREP: gcs_caused\(\) returned .*|, qr|WSREP: Protocol violation. JOIN message sender .* is not in state transfer \(SYNCED\). Message ignored.|, qr(WSREP: Action message in non-primary configuration from member [0-9]*), + qr(WSREP: discarding established .*), ); diff --git a/mysql-test/suite/galera/t/galera_split_brain.test b/mysql-test/suite/galera/t/galera_split_brain.test index 22f6370241c..a85a2ad9b8d 100644 --- a/mysql-test/suite/galera/t/galera_split_brain.test +++ b/mysql-test/suite/galera/t/galera_split_brain.test @@ -25,11 +25,8 @@ CREATE TABLE t1 (f1 INTEGER) ENGINE=InnoDB; # Reset the master and restart the slave so that post-test checks can run -SET GLOBAL wsrep_cluster_address = ''; ---disable_query_log ---eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_orig'; ---enable_query_log +--connection node_2 --source include/start_mysqld.inc --sleep 5 --source include/wait_until_connected_again.inc diff --git a/mysql-test/suite/galera/t/galera_var_cluster_address.test b/mysql-test/suite/galera/t/galera_var_cluster_address.test index 17e77a9b5af..740c38765f6 100644 --- a/mysql-test/suite/galera/t/galera_var_cluster_address.test +++ b/mysql-test/suite/galera/t/galera_var_cluster_address.test @@ -5,12 +5,17 @@ --source include/galera_cluster.inc --source include/have_innodb.inc +# Save original auto_increment_offset values. +--let $node_1=node_1 +--let $node_2=node_2 +--source include/auto_increment_offset_save.inc + # # Set to invalid value # ---connection node_1 ---let $wsrep_cluster_address_node1 = `SELECT @@wsrep_cluster_address` +--connection node_2 +--let $wsrep_cluster_address_node2 = `SELECT @@wsrep_cluster_address` SET GLOBAL wsrep_cluster_address = 'foo://'; # With wsrep_sync_wait, this returns an error @@ -20,7 +25,7 @@ SET GLOBAL wsrep_cluster_address = 'foo://'; SET SESSION wsrep_sync_wait=0; --error ER_UNKNOWN_COM_ERROR -SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS; +SELECT COUNT(*) > 0 FROM INFORMATION_SCHEMA.GLOBAL_STATUS; # Must return 'OFF' SHOW STATUS LIKE 'wsrep_ready'; @@ -32,9 +37,9 @@ SHOW STATUS LIKE 'wsrep_cluster_status'; SHOW STATUS LIKE 'wsrep_local_state'; SHOW STATUS LIKE 'wsrep_local_state_comment'; ---connection node_2 +--connection node_1 --sleep 1 -# Node #2 thinks that it is now part of a single-node primary cluster +# Node #1 thinks that it is now part of a single-node primary cluster SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; @@ -42,13 +47,10 @@ SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VA # Reset everything as it was # ---connection node_1 ---disable_query_log ---eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node1'; ---enable_query_log - --connection node_2 -SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; +--disable_query_log +--eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node2'; +--enable_query_log --source include/wait_until_connected_again.inc @@ -56,40 +58,20 @@ SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; -# -# Set to invalid host -# - ---connection node_1 -SET GLOBAL wsrep_cluster_address = 'gcomm://192.0.2.1'; - ---error ER_UNKNOWN_COM_ERROR -SELECT * FROM INFORMATION_SCHEMA.GLOBAL_STATUS; - -# Must return 'OFF' -SHOW STATUS LIKE 'wsrep_ready'; - -# Must return 'Non-primary' -SHOW STATUS LIKE 'wsrep_cluster_status'; - -# Must return 0 = 'Initialized' -SHOW STATUS LIKE 'wsrep_local_state'; -SHOW STATUS LIKE 'wsrep_local_state_comment'; - -# -# Reset everything as it was -# - ---connection node_1 ---disable_query_log ---eval SET GLOBAL wsrep_cluster_address = '$wsrep_cluster_address_node1'; ---enable_query_log - --connection node_2 -SET GLOBAL wsrep_cluster_address = @@wsrep_cluster_address; ---sleep 1 +CALL mtr.add_suppression("Backend not supported: foo"); +CALL mtr.add_suppression("Failed to initialize backend using 'foo"); +CALL mtr.add_suppression("Failed to open channel 'my_wsrep_cluster' at 'foo"); +CALL mtr.add_suppression("gcs connect failed: Socket type not supported"); +CALL mtr.add_suppression("wsrep::connect\\(\\) failed: 7"); +CALL mtr.add_suppression("gcs_caused\\(\\) returned -103 \\(Software caused connection abort\\)"); +CALL mtr.add_suppression("failed to open gcomm backend connection: 110: failed to reach primary view: 110"); +CALL mtr.add_suppression("Failed to open backend connection: -110 \\(Connection timed out\\)"); +CALL mtr.add_suppression("gcs connect failed: Connection timed out"); +CALL mtr.add_suppression("WSREP: wsrep::connect\\(foo://\\) failed: 7"); ---connection node_1 -SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status'; -SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; +# Restore original auto_increment_offset values. +--source include/auto_increment_offset_restore.inc +--source include/galera_end.inc +--echo # End of test diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test index 0c81779ca65..7a76a71a265 100644 --- a/mysql-test/suite/galera/t/galera_var_dirty_reads.test +++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test @@ -36,12 +36,18 @@ SET @@session.wsrep_dirty_reads=ON; SELECT * FROM t1; -#Select query which does not access table should be allowed MDEV-11016 +--echo # +--echo # MDEV-11016: wsrep_node_is_ready() check is too strict +--echo # SET @@session.wsrep_dirty_reads=OFF; SELECT 2; -SELECT @@max_allowed_packet; SELECT 2+2 from DUAL; -SELECT sysdate() from DUAL; +SET @VAR=1; +SELECT @VAR; +--disable_result_log +SELECT @@max_allowed_packet; +SELECT SYSDATE() from DUAL; +--enable_result_log --disable_query_log --eval SET @@global.wsrep_cluster_address = '$wsrep_cluster_address_saved' From ffdd1e9d888edc4e147c3b316a87468b000f8dd4 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Wed, 14 Dec 2016 13:57:05 +0530 Subject: [PATCH 07/11] Revert "MDEV-11016 wsrep_node_is_ready() check is too strict" This reverts commit 52ea5ad865b4f6b4b37176296a3be0a716c5109a. # Conflicts: # mysql-test/suite/galera/r/galera_var_dirty_reads.result # mysql-test/suite/galera/t/galera_var_dirty_reads.test # sql/sql_parse.cc --- .../suite/galera/r/galera_var_dirty_reads.result | 16 ---------------- .../suite/galera/t/galera_var_dirty_reads.test | 13 ------------- sql/sql_parse.cc | 4 ---- 3 files changed, 33 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result index c0ffb2d4860..6d703c8cf95 100644 --- a/mysql-test/suite/galera/r/galera_var_dirty_reads.result +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -18,22 +18,6 @@ SET @@session.wsrep_dirty_reads=ON; SELECT * FROM t1; i 1 -# -# MDEV-11016: wsrep_node_is_ready() check is too strict -# -SET @@session.wsrep_dirty_reads=OFF; -SELECT 2; -2 -2 -SELECT 2+2 from DUAL; -2+2 -4 -SET @VAR=1; -SELECT @VAR; -@VAR -1 -SELECT @@max_allowed_packet; -SELECT SYSDATE() from DUAL; SELECT * FROM t1; i 1 diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test index 7a76a71a265..dfd8d5ecf29 100644 --- a/mysql-test/suite/galera/t/galera_var_dirty_reads.test +++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test @@ -36,19 +36,6 @@ SET @@session.wsrep_dirty_reads=ON; SELECT * FROM t1; ---echo # ---echo # MDEV-11016: wsrep_node_is_ready() check is too strict ---echo # -SET @@session.wsrep_dirty_reads=OFF; -SELECT 2; -SELECT 2+2 from DUAL; -SET @VAR=1; -SELECT @VAR; ---disable_result_log -SELECT @@max_allowed_packet; -SELECT SYSDATE() from DUAL; ---enable_result_log - --disable_query_log --eval SET @@global.wsrep_cluster_address = '$wsrep_cluster_address_saved' --enable_query_log diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 53350751d79..4ed1b7a5323 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2635,15 +2635,11 @@ mysql_execute_command(THD *thd) /* Bail out if DB snapshot has not been installed. We however, allow SET and SHOW queries. - SHOW and SELECT queries (only if wsrep_dirty_reads is set or when it - does not access ant table) */ if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && lex->sql_command != SQLCOM_SET_OPTION && !(thd->variables.wsrep_dirty_reads && lex->sql_command == SQLCOM_SELECT) && - !(lex->sql_command == SQLCOM_SELECT && - !all_tables) && !wsrep_is_show_query(lex->sql_command)) { my_message(ER_UNKNOWN_COM_ERROR, From 4c1e181ac5eac55c67705ffe29b48a5d832211be Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Wed, 14 Dec 2016 15:22:04 +0530 Subject: [PATCH 08/11] MDEV-11479 Improved wsrep_dirty_reads Tasks:- Changes in wsrep_dirty_reads variable 1.) Global + Session scope (Current: session-only) 2.) Can be set using command line. 3.) Allow all commands that do not change data (besides SELECT) 4.) Allow prepared Statements that do not change data 5.) Works with wsrep_sync_wait enabled --- mysql-test/r/mysqld--help.result | 3 + .../galera/r/galera_var_dirty_reads.result | 70 +++++++++++++++++++ .../galera/t/galera_var_dirty_reads.test | 68 ++++++++++++++++++ .../sys_vars/r/wsrep_dirty_reads_basic.result | 23 +++++- .../sys_vars/t/wsrep_dirty_reads_basic.test | 17 ++++- sql/sql_parse.cc | 9 ++- sql/sys_vars.cc | 5 +- sql/wsrep_mysqld.cc | 4 ++ sql/wsrep_mysqld.h | 1 + 9 files changed, 191 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 8ff9073b625..e911f0b8db6 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -1080,6 +1080,8 @@ The following options may be given as the first argument: DBUG options to provider library --wsrep-debug To enable debug level logging --wsrep-desync To desynchronize the node from the cluster + --wsrep-dirty-reads Allow reads even when the node is not in the primary + component. --wsrep-drupal-282555-workaround To use a workaround forbad autoincrement value --wsrep-forced-binlog-format=name @@ -1454,6 +1456,7 @@ wsrep-convert-LOCK-to-trx FALSE wsrep-dbug-option wsrep-debug FALSE wsrep-desync FALSE +wsrep-dirty-reads FALSE wsrep-drupal-282555-workaround FALSE wsrep-forced-binlog-format NONE wsrep-load-data-splitting TRUE diff --git a/mysql-test/suite/galera/r/galera_var_dirty_reads.result b/mysql-test/suite/galera/r/galera_var_dirty_reads.result index 6d703c8cf95..8a3175912c7 100644 --- a/mysql-test/suite/galera/r/galera_var_dirty_reads.result +++ b/mysql-test/suite/galera/r/galera_var_dirty_reads.result @@ -3,6 +3,10 @@ INSERT INTO t1 VALUES(1); SELECT * FROM t1; i 1 +create user user1; +grant all privileges on *.* to user1; +create user user2; +grant all privileges on *.* to user2; SET @@global.wsrep_cluster_address = ''; SET @@session.wsrep_dirty_reads=OFF; SET SESSION wsrep_sync_wait=0; @@ -18,8 +22,74 @@ SET @@session.wsrep_dirty_reads=ON; SELECT * FROM t1; i 1 +connect con1, localhost, user1,,test,$NODE_MYPORT_2,$NODE_MYSOCK_2; +SET SESSION wsrep_sync_wait=0; +set session wsrep_dirty_reads=1; +prepare stmt_show from 'select 1'; +prepare stmt_select from 'select * from t1'; +prepare stmt_insert from 'insert into t1 values(1)'; +set session wsrep_dirty_reads=0; +execute stmt_show; +ERROR 08S01: WSREP has not yet prepared node for application use +execute stmt_select; +ERROR 08S01: WSREP has not yet prepared node for application use +execute stmt_insert; +ERROR 08S01: WSREP has not yet prepared node for application use +SET wsrep_dirty_reads=ON; +select @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +1 +execute stmt_show; +1 +1 +execute stmt_select; +i +1 +execute stmt_insert; +ERROR 08S01: WSREP has not yet prepared node for application use +SET @@global.wsrep_dirty_reads=ON; +connect con2, localhost, user2,,test,$NODE_MYPORT_2,$NODE_MYSOCK_2; +select @@session.wsrep_dirty_reads; +@@session.wsrep_dirty_reads +1 +prepare stmt_show from 'select 1'; +prepare stmt_select from 'select * from t1'; +prepare stmt_insert from 'insert into t1 values(1)'; +execute stmt_show; +1 +1 +execute stmt_select; +i +1 +execute stmt_insert; +ERROR 08S01: WSREP has not yet prepared node for application use +SET SESSION wsrep_sync_wait=1; +execute stmt_show; +1 +1 +execute stmt_select; +i +1 +execute stmt_insert; +ERROR 08S01: WSREP has not yet prepared node for application use +SET SESSION wsrep_sync_wait=7; +execute stmt_show; +1 +1 +execute stmt_select; +i +1 +execute stmt_insert; +ERROR 08S01: WSREP has not yet prepared node for application use +connection node_2; +SET @@global.wsrep_dirty_reads=OFF; +connection node_1; SELECT * FROM t1; i 1 DROP TABLE t1; +drop user user1; +drop user user2; +disconnect node_2; +disconnect node_1; # End of test diff --git a/mysql-test/suite/galera/t/galera_var_dirty_reads.test b/mysql-test/suite/galera/t/galera_var_dirty_reads.test index dfd8d5ecf29..bcdb1574a3d 100644 --- a/mysql-test/suite/galera/t/galera_var_dirty_reads.test +++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test @@ -17,6 +17,11 @@ CREATE TABLE t1(i INT) ENGINE=INNODB; INSERT INTO t1 VALUES(1); SELECT * FROM t1; +create user user1; +grant all privileges on *.* to user1; +create user user2; +grant all privileges on *.* to user2; + SET @@global.wsrep_cluster_address = ''; SET @@session.wsrep_dirty_reads=OFF; @@ -36,6 +41,67 @@ SET @@session.wsrep_dirty_reads=ON; SELECT * FROM t1; +--enable_connect_log +--connect (con1, localhost, user1,,test,$NODE_MYPORT_2,$NODE_MYSOCK_2) +#Just test the session behavior +SET SESSION wsrep_sync_wait=0; + +set session wsrep_dirty_reads=1; +#Prepared statement creation should be allowed MDEV-11479 +prepare stmt_show from 'select 1'; +prepare stmt_select from 'select * from t1'; +prepare stmt_insert from 'insert into t1 values(1)'; +set session wsrep_dirty_reads=0; + +#No Preapare stmt/proceure will be allowed +--error ER_UNKNOWN_COM_ERROR +execute stmt_show; +--error ER_UNKNOWN_COM_ERROR +execute stmt_select; +--error ER_UNKNOWN_COM_ERROR +execute stmt_insert; + +SET wsrep_dirty_reads=ON; +select @@session.wsrep_dirty_reads; +#Only prepare statement which does not change data should be allowed +execute stmt_show; +execute stmt_select; +--error ER_UNKNOWN_COM_ERROR +execute stmt_insert; +SET @@global.wsrep_dirty_reads=ON; + +--connect (con2, localhost, user2,,test,$NODE_MYPORT_2,$NODE_MYSOCK_2) +#Just test the session behavior +select @@session.wsrep_dirty_reads; + +prepare stmt_show from 'select 1'; +prepare stmt_select from 'select * from t1'; +prepare stmt_insert from 'insert into t1 values(1)'; + +#Only prepare statement which does not change data should be allowed +execute stmt_show; +execute stmt_select; +--error ER_UNKNOWN_COM_ERROR +execute stmt_insert; + +#wsrep_dirty_read should work when wsrep_sync_wait is 1 or non zero +#because we already are disconnected , So It does not make any sense +#to wait for other nodes +SET SESSION wsrep_sync_wait=1; +execute stmt_show; +execute stmt_select; +--error ER_UNKNOWN_COM_ERROR +execute stmt_insert; + +SET SESSION wsrep_sync_wait=7; +execute stmt_show; +execute stmt_select; +--error ER_UNKNOWN_COM_ERROR +execute stmt_insert; + +--connection node_2 +SET @@global.wsrep_dirty_reads=OFF; + --disable_query_log --eval SET @@global.wsrep_cluster_address = '$wsrep_cluster_address_saved' --enable_query_log @@ -45,6 +111,8 @@ SELECT * FROM t1; SELECT * FROM t1; # Cleanup DROP TABLE t1; +drop user user1; +drop user user2; # Restore original auto_increment_offset values. --source include/auto_increment_offset_restore.inc diff --git a/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result b/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result index d2a62d6136f..1968103873a 100644 --- a/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result +++ b/mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result @@ -5,12 +5,13 @@ SET @wsrep_dirty_reads_session_saved = @@session.wsrep_dirty_reads; # default SELECT @@global.wsrep_dirty_reads; -ERROR HY000: Variable 'wsrep_dirty_reads' is a SESSION variable +@@global.wsrep_dirty_reads +0 SELECT @@session.wsrep_dirty_reads; @@session.wsrep_dirty_reads 0 -# scope and valid values +# valid values for session SET @@session.wsrep_dirty_reads=OFF; SELECT @@session.wsrep_dirty_reads; @@session.wsrep_dirty_reads @@ -24,11 +25,29 @@ SELECT @@session.wsrep_dirty_reads; @@session.wsrep_dirty_reads 0 +# valid values for global +SET @@global.wsrep_dirty_reads=OFF; +SELECT @@global.wsrep_dirty_reads; +@@global.wsrep_dirty_reads +0 +SET @@global.wsrep_dirty_reads=ON; +SELECT @@global.wsrep_dirty_reads; +@@global.wsrep_dirty_reads +1 +SET @@global.wsrep_dirty_reads=default; +SELECT @@global.wsrep_dirty_reads; +@@global.wsrep_dirty_reads +0 + # invalid values SET @@session.wsrep_dirty_reads=NULL; ERROR 42000: Variable 'wsrep_dirty_reads' can't be set to the value of 'NULL' SET @@session.wsrep_dirty_reads='junk'; ERROR 42000: Variable 'wsrep_dirty_reads' can't be set to the value of 'junk' +SET @@global.wsrep_dirty_reads=NULL; +ERROR 42000: Variable 'wsrep_dirty_reads' can't be set to the value of 'NULL' +SET @@global.wsrep_dirty_reads='junk'; +ERROR 42000: Variable 'wsrep_dirty_reads' can't be set to the value of 'junk' # restore the initial values SET @@session.wsrep_dirty_reads = @wsrep_dirty_reads_session_saved; diff --git a/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test b/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test index a47524fcfe3..ffe767a051b 100644 --- a/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test +++ b/mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test @@ -8,12 +8,12 @@ SET @wsrep_dirty_reads_session_saved = @@session.wsrep_dirty_reads; --echo # default ---error ER_INCORRECT_GLOBAL_LOCAL_VAR + SELECT @@global.wsrep_dirty_reads; SELECT @@session.wsrep_dirty_reads; --echo ---echo # scope and valid values +--echo # valid values for session SET @@session.wsrep_dirty_reads=OFF; SELECT @@session.wsrep_dirty_reads; SET @@session.wsrep_dirty_reads=ON; @@ -21,12 +21,25 @@ SELECT @@session.wsrep_dirty_reads; SET @@session.wsrep_dirty_reads=default; SELECT @@session.wsrep_dirty_reads; +--echo +--echo # valid values for global +SET @@global.wsrep_dirty_reads=OFF; +SELECT @@global.wsrep_dirty_reads; +SET @@global.wsrep_dirty_reads=ON; +SELECT @@global.wsrep_dirty_reads; +SET @@global.wsrep_dirty_reads=default; +SELECT @@global.wsrep_dirty_reads; + --echo --echo # invalid values --error ER_WRONG_VALUE_FOR_VAR SET @@session.wsrep_dirty_reads=NULL; --error ER_WRONG_VALUE_FOR_VAR SET @@session.wsrep_dirty_reads='junk'; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_dirty_reads=NULL; +--error ER_WRONG_VALUE_FOR_VAR +SET @@global.wsrep_dirty_reads='junk'; --echo --echo # restore the initial values diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4ed1b7a5323..d92ef810498 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2633,13 +2633,16 @@ mysql_execute_command(THD *thd) } /* - Bail out if DB snapshot has not been installed. We however, - allow SET and SHOW queries. + Bail out if DB snapshot has not been installed. SET and SHOW commands, + however, are always allowed. + + We additionally allow all other commands that do not change data in + case wsrep_dirty_reads is enabled. */ if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && lex->sql_command != SQLCOM_SET_OPTION && !(thd->variables.wsrep_dirty_reads && - lex->sql_command == SQLCOM_SELECT) && + !is_update_query(lex->sql_command)) && !wsrep_is_show_query(lex->sql_command)) { my_message(ER_UNKNOWN_COM_ERROR, diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index af440d7ac44..93a863d6b88 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4811,8 +4811,9 @@ static Sys_var_mybool Sys_wsrep_restart_slave( GLOBAL_VAR(wsrep_restart_slave), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); static Sys_var_mybool Sys_wsrep_dirty_reads( - "wsrep_dirty_reads", "Do not reject SELECT queries even when the node " - "is not ready.", SESSION_ONLY(wsrep_dirty_reads), NO_CMD_LINE, + "wsrep_dirty_reads", + "Allow reads even when the node is not in the primary component.", + SESSION_VAR(wsrep_dirty_reads), CMD_LINE(OPT_ARG), DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG); #endif /* WITH_WSREP */ diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 13b72b65afe..353911dcfde 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -71,6 +71,8 @@ my_bool wsrep_restart_slave_activated = 0; // node has dropped, and slave // restart will be needed my_bool wsrep_slave_UK_checks = 0; // slave thread does UK checks my_bool wsrep_slave_FK_checks = 0; // slave thread does FK checks +// Allow reads even if the node is not in the primary component. +bool wsrep_dirty_reads = false; /* Set during the creation of first wsrep applier and rollback threads. @@ -816,6 +818,8 @@ bool wsrep_must_sync_wait (THD* thd, uint mask) { return (thd->variables.wsrep_sync_wait & mask) && thd->variables.wsrep_on && + !(thd->variables.wsrep_dirty_reads && + !is_update_query(thd->lex->sql_command)) && !thd->in_active_multi_stmt_transaction() && thd->wsrep_conflict_state != REPLAYING && thd->wsrep_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED; diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index 57382d27e98..5ec183f7186 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -88,6 +88,7 @@ extern ulong wsrep_retry_autocommit; extern my_bool wsrep_auto_increment_control; extern my_bool wsrep_drupal_282555_workaround; extern my_bool wsrep_incremental_data_collection; +extern bool wsrep_dirty_reads; extern const char* wsrep_start_position; extern ulong wsrep_max_ws_size; extern ulong wsrep_max_ws_rows; From be430b80df0cdd4eba32df1570195721dbfd1b39 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Wed, 21 Dec 2016 09:34:37 +0530 Subject: [PATCH 09/11] MDEV-11490 Galera_3nodes test suite does not suppress Warnings. Problem:- While running individual tests of Galera_3nodes , We get warnings like '[Warning] WSREP: Could not open state file for reading: '. And because of this individual tests fails. Solution:- We change suite.pm of Galera_3nodes to supress these warnings. --- mysql-test/suite/galera_3nodes/suite.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/galera_3nodes/suite.pm b/mysql-test/suite/galera_3nodes/suite.pm index 39d5acbcc1b..c91e6e07d76 100644 --- a/mysql-test/suite/galera_3nodes/suite.pm +++ b/mysql-test/suite/galera_3nodes/suite.pm @@ -26,6 +26,7 @@ push @::global_suppressions, ( qr(WSREP: wsrep_sst_receive_address is set to '127.0.0.1), qr(WSREP: Could not open saved state file for reading: ), + qr(WSREP: Could not open state file for reading: ), qr(WSREP: Gap in state sequence. Need state transfer.), qr(WSREP: Failed to prepare for incremental state transfer:), qr(WSREP:.*down context.*), @@ -33,13 +34,14 @@ push @::global_suppressions, qr(WSREP: last inactive check more than .* skipping check), qr(WSREP: SQL statement was ineffective), qr(WSREP: Releasing seqno [0-9]* before [0-9]* was assigned.), - qr|WSREP: access file\(gvwstate.dat\) failed\(No such file or directory\)|, + qr|WSREP: access file\(.*gvwstate.dat\) failed\(No such file or directory\)|, qr(WSREP: Quorum: No node with complete state), qr(WSREP: Initial position was provided by configuration or SST, avoiding override), qr|WSREP: discarding established \(time wait\) .*|, qr(WSREP: There are no nodes in the same segment that will ever be able to become donors, yet there is a suitable donor outside. Will use that one.), qr(WSREP: evs::proto.*), qr|WSREP: Ignoring possible split-brain (allowed by configuration) from view:.*|, + qr(WSREP: Member .* requested state transfer from .* but it is impossible to select State Transfer donor: Resource temporarily unavailable), qr(WSREP: Could not find peer:), qr(WSREP: Protocol violation. JOIN message sender .*), qr(WSREP: JOIN message from member [0-9]* in non-primary configuration. Ignored.), From 11544334a277508fb984c0a5bba8faa6b97a2762 Mon Sep 17 00:00:00 2001 From: Sachin Setiya Date: Tue, 27 Dec 2016 14:13:32 +0530 Subject: [PATCH 10/11] MDEV-11636 Extra persistent columns on slave always gets NULL in RBR Problem:- In replication if slave has extra persistent column then these column are not computed while applying write-set from master. Solution:- While applying row events from server, we will generate values for extra persistent columns. --- .../rpl/r/rpl_alter_extra_persistent.result | 220 ++++++++++++++++++ .../rpl/t/rpl_alter_extra_persistent.test | 106 +++++++++ sql/rpl_record.cc | 31 +++ sql/rpl_record.h | 1 + 4 files changed, 358 insertions(+) create mode 100644 mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result create mode 100644 mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test diff --git a/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result b/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result new file mode 100644 index 00000000000..84915073d87 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_alter_extra_persistent.result @@ -0,0 +1,220 @@ +include/master-slave.inc +[connection master] +connection master; +create table t1(a int primary key); +insert into t1 values(1); +insert into t1 values(2); +insert into t1 values(3); +insert into t1 values(4); +connection slave; +select * from t1 order by a; +a +1 +2 +3 +4 +alter table t1 add column z1 int as(a+1) virtual, add column z2 int as (a+2) persistent; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +connection master; +insert into t1 values(5); +insert into t1 values(6); +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#UPDATE query +connection master; +update t1 set a = a+10; +select * from t1 order by a; +a +11 +12 +13 +14 +15 +16 +connection slave; +select * from t1 order by a; +a z1 z2 +11 12 13 +12 13 14 +13 14 15 +14 15 16 +15 16 17 +16 17 18 +connection master; +update t1 set a = a-10; +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#DELETE quert +connection master; +delete from t1 where a > 2 and a < 4; +select * from t1 order by a; +a +1 +2 +4 +5 +6 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +4 5 6 +5 6 7 +6 7 8 +#REPLACE query +connection master; +replace into t1 values(1); +replace into t1 values(3); +replace into t1 values(1); +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#SELECT query +connection master; +select * from t1 where a > 2 and a < 4; +a +3 +connection slave; +select * from t1 where a > 2 and a < 4; +a z1 z2 +3 4 5 +#UPDATE with SELECT query +connection master; +update t1 set a = a + 10 where a > 2 and a < 4; +select * from t1 order by a; +a +1 +2 +4 +5 +6 +13 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +4 5 6 +5 6 7 +6 7 8 +13 14 15 +connection master; +update t1 set a = a - 10 where a = 13; +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +#Break Unique Constraint +alter table t1 add column z4 int as (a % 6) persistent unique; +connection master; +#entering duplicate value for slave persistent column +insert into t1 values(7); +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +7 +connection slave; +include/wait_for_slave_sql_error.inc [errno=1062] +connection slave; +connection slave; +select * from t1 order by a; +a z1 z2 z4 +1 2 3 1 +2 3 4 2 +3 4 5 3 +4 5 6 4 +5 6 7 5 +6 7 8 0 +alter table t1 drop column z4; +start slave; +include/wait_for_slave_sql_to_start.inc +connection slave; +connection slave; +connection master; +connection slave; +select * from t1 order by a; +a z1 z2 +1 2 3 +2 3 4 +3 4 5 +4 5 6 +5 6 7 +6 7 8 +7 8 9 +connection master; +select * from t1 order by a; +a +1 +2 +3 +4 +5 +6 +7 +drop table t1; +include/rpl_end.inc +connection server_2; +connection server_2; +connection server_2; +connection server_2; +connection server_1; +connection server_1; +connection server_1; +connection server_2; +connection server_1; +connection server_2; +connection server_2; +connection server_1; +connection server_1; diff --git a/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test b/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test new file mode 100644 index 00000000000..3b2fff1cb13 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_alter_extra_persistent.test @@ -0,0 +1,106 @@ +--source include/master-slave.inc +--source include/have_binlog_format_row.inc + +--enable_connect_log +--connection master +create table t1(a int primary key); +insert into t1 values(1); +insert into t1 values(2); +insert into t1 values(3); +insert into t1 values(4); + +--sync_slave_with_master +select * from t1 order by a; +alter table t1 add column z1 int as(a+1) virtual, add column z2 int as (a+2) persistent; +select * from t1 order by a; + +--connection master +insert into t1 values(5); +insert into t1 values(6); + +--sync_slave_with_master +select * from t1 order by a; + + +--echo #UPDATE query + +--connection master +update t1 set a = a+10; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--connection master +update t1 set a = a-10; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #DELETE quert +--connection master +delete from t1 where a > 2 and a < 4; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #REPLACE query +--connection master +replace into t1 values(1); +replace into t1 values(3); +replace into t1 values(1); + +--sync_slave_with_master +select * from t1 order by a; + +--echo #SELECT query +--connection master +select * from t1 where a > 2 and a < 4; + +--connection slave +select * from t1 where a > 2 and a < 4; + +--echo #UPDATE with SELECT query +--connection master +update t1 set a = a + 10 where a > 2 and a < 4; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--connection master +update t1 set a = a - 10 where a = 13; +select * from t1 order by a; + +--sync_slave_with_master +select * from t1 order by a; + +--echo #Break Unique Constraint +alter table t1 add column z4 int as (a % 6) persistent unique; + +--connection master + +--echo #entering duplicate value for slave persistent column +insert into t1 values(7); +select * from t1 order by a; + +--connection slave +--let $slave_sql_errno= 1062 +--source include/wait_for_slave_sql_error.inc +select * from t1 order by a; +alter table t1 drop column z4; +start slave; + +--source include/wait_for_slave_sql_to_start.inc + +--connection master +--sync_slave_with_master +select * from t1 order by a; + +--connection master +select * from t1 order by a; +drop table t1; + +--source include/rpl_end.inc diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index df8036c40d8..21b8a8028a6 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -407,6 +407,12 @@ unpack_row(rpl_group_info *rgi, } } + /* + Add Extra slave persistent columns + */ + if ((error= fill_extra_persistent_columns(table, cols->n_bits))) + DBUG_RETURN(error); + /* We should now have read all the null bytes, otherwise something is really wrong. @@ -479,5 +485,30 @@ int prepare_record(TABLE *const table, const uint skip, const bool check) DBUG_RETURN(0); } +/** + Fills @c table->record[0] with computed values of extra persistent column which are present on slave but not on master. + @param table Table whose record[0] buffer is prepared. + @param master_cols No of columns on master + @returns 0 on success + */ +int fill_extra_persistent_columns(TABLE *table, int master_cols) +{ + int error= 0; + Field **vfield_ptr, *vfield; + if (!table->vfield) + return 0; + for (vfield_ptr= table->vfield; *vfield_ptr; ++vfield_ptr) + { + vfield= *vfield_ptr; + if (vfield->field_index >= master_cols && vfield->stored_in_db) + { + /*Set bitmap for writing*/ + bitmap_set_bit(table->vcol_set, vfield->field_index); + error= vfield->vcol_info->expr_item->save_in_field(vfield,0); + bitmap_clear_bit(table->vcol_set, vfield->field_index); + } + } + return error; +} #endif // HAVE_REPLICATION diff --git a/sql/rpl_record.h b/sql/rpl_record.h index c10eb8225b0..be69716d9d5 100644 --- a/sql/rpl_record.h +++ b/sql/rpl_record.h @@ -38,6 +38,7 @@ int unpack_row(rpl_group_info *rgi, // Fill table's record[0] with default values. int prepare_record(TABLE *const table, const uint skip, const bool check); +int fill_extra_persistent_columns(TABLE *table, int master_cols); #endif #endif From 5fc1ba604e27b7d9eaa2977ef5b0c180f6f62565 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 13 Jan 2017 13:57:17 -0500 Subject: [PATCH 11/11] Fix for post-merge build failure. --- storage/xtradb/handler/ha_innodb.cc | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index ea6a08fc156..ea94f90cbf8 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -7340,16 +7340,7 @@ wsrep_store_key_val_for_row( blob_data = row_mysql_read_blob_ref(&blob_len, (byte*) (record + (ulint) get_field_offset(table, field)), - (ulint) field->pack_length(), -#ifdef HAVE_PERCONA_COMPRESSED_COLUMNS - field->column_format() == - COLUMN_FORMAT_TYPE_COMPRESSED, - reinterpret_cast( - field->zip_dict_data.str), - field->zip_dict_data.length, prebuilt); -#else - 0, 0, 0, prebuilt); -#endif + (ulint) field->pack_length()); true_len = blob_len; @@ -9103,9 +9094,7 @@ wsrep_calc_row_hash( switch (col_type) { case DATA_BLOB: - ptr = row_mysql_read_blob_ref(&len, ptr, len, - false, 0, 0, prebuilt); - + ptr = row_mysql_read_blob_ref(&len, ptr, len); break; case DATA_VARCHAR: