summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSachin Setiya <sachinsetia1001@gmail.com>2016-12-14 17:14:42 +0530
committerSachin Setiya <sachinsetia1001@gmail.com>2016-12-14 17:14:42 +0530
commit5ddd8149e44122feb0989b9944113d2b92d6f84a (patch)
treebaa490d8ee88ad74f5b9be88c445b6fd228eef60
parent95422c445db7db60fca688711d98955e59e009e2 (diff)
downloadmariadb-git-5ddd8149e44122feb0989b9944113d2b92d6f84a.tar.gz
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
-rw-r--r--mysql-test/r/mysqld--help.result3
-rw-r--r--mysql-test/suite/galera/r/galera_var_dirty_reads.result70
-rw-r--r--mysql-test/suite/galera/t/galera_var_dirty_reads.test68
-rw-r--r--mysql-test/suite/sys_vars/r/wsrep_dirty_reads_basic.result23
-rw-r--r--mysql-test/suite/sys_vars/t/wsrep_dirty_reads_basic.test17
-rw-r--r--sql/sql_parse.cc9
-rw-r--r--sql/sys_vars.cc5
-rw-r--r--sql/wsrep_mysqld.cc4
-rw-r--r--sql/wsrep_mysqld.h1
9 files changed, 191 insertions, 9 deletions
diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result
index 61243e02363..34d4bae0f28 100644
--- a/mysql-test/r/mysqld--help.result
+++ b/mysql-test/r/mysqld--help.result
@@ -879,6 +879,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
@@ -1201,6 +1203,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 9eea8efdaf3..8fd3b1d22f2 100644
--- a/mysql-test/suite/galera/t/galera_var_dirty_reads.test
+++ b/mysql-test/suite/galera/t/galera_var_dirty_reads.test
@@ -20,6 +20,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;
@@ -39,6 +44,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
@@ -48,6 +114,8 @@ SELECT * FROM t1;
SELECT * FROM t1;
# Cleanup
DROP TABLE t1;
+drop user user1;
+drop user user2;
--disable_query_log
# Restore original auto_increment_offset values.
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;
@@ -22,11 +22,24 @@ 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 48addaab143..ec6eb0e6f87 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2386,13 +2386,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))
{
#if DIRTY_HACK
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index bdcedfff5a3..e0de7960ec9 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -3966,8 +3966,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 48114fcba34..21c7e94096d 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -65,6 +65,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.
@@ -894,6 +896,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 3fb5189937e..85d4cea241f 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -80,6 +80,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;