Query classifier ignored implicit commits in cases of write commands. Fixed it.

Added more tests for transaction support. Mostly different cases where some command triggers implicit commit in the middle of transaction.
This commit is contained in:
VilhoRaatikka 2014-03-28 00:16:18 +02:00
parent 40b7ce6d43
commit 7c3a354fd8
11 changed files with 184 additions and 43 deletions

View File

@ -396,34 +396,7 @@ static skygw_query_type_t resolve_query_type(
type = QUERY_TYPE_SESSION_WRITE;
goto return_qtype;
}
/**
* 1:ALTER TABLE, TRUNCATE, REPAIR, OPTIMIZE, ANALYZE, CHECK.
* 2:CREATE|ALTER|DROP|TRUNCATE|RENAME TABLE, LOAD, CREATE|DROP|ALTER DB,
* CREATE|DROP INDEX, CREATE|DROP VIEW, CREATE|DROP TRIGGER,
* CREATE|ALTER|DROP EVENT, UPDATE, INSERT, INSERT(SELECT),
* DELETE, REPLACE, REPLACE(SELECT), CREATE|RENAME|DROP USER,
* GRANT, REVOKE, OPTIMIZE, CREATE|ALTER|DROP FUNCTION|PROCEDURE,
* CREATE SPFUNCTION, INSTALL|UNINSTALL PLUGIN
*/
if (is_log_table_write_query(lex->sql_command) ||
is_update_query(lex->sql_command))
{
if (thd->variables.sql_log_bin == 0 &&
force_data_modify_op_replication)
{
type |= QUERY_TYPE_SESSION_WRITE;
} else {
type |= QUERY_TYPE_WRITE;
}
goto return_qtype;
}
/**
* REVOKE ALL, ASSIGN_TO_KEYCACHE,
* PRELOAD_KEYS, FLUSH, RESET, CREATE|ALTER|DROP SERVER
* SET autocommit, various other SET commands.
*/
if (skygw_stmt_causes_implicit_commit(lex, CF_AUTO_COMMIT_TRANS))
{
if (LOG_IS_ENABLED(LOGFILE_TRACE))
@ -446,21 +419,47 @@ static skygw_query_type_t resolve_query_type(
}
}
type |= QUERY_TYPE_COMMIT;
if (lex->option_type == OPT_GLOBAL)
}
/**
* REVOKE ALL, ASSIGN_TO_KEYCACHE,
* PRELOAD_KEYS, FLUSH, RESET, CREATE|ALTER|DROP SERVER
*/
if (lex->option_type == OPT_GLOBAL)
{
type |= QUERY_TYPE_GLOBAL_WRITE;
goto return_qtype;
}
else if (lex->option_type == OPT_SESSION)
{
type |= QUERY_TYPE_SESSION_WRITE;
goto return_qtype;
}
/**
* 1:ALTER TABLE, TRUNCATE, REPAIR, OPTIMIZE, ANALYZE, CHECK.
* 2:CREATE|ALTER|DROP|TRUNCATE|RENAME TABLE, LOAD, CREATE|DROP|ALTER DB,
* CREATE|DROP INDEX, CREATE|DROP VIEW, CREATE|DROP TRIGGER,
* CREATE|ALTER|DROP EVENT, UPDATE, INSERT, INSERT(SELECT),
* DELETE, REPLACE, REPLACE(SELECT), CREATE|RENAME|DROP USER,
* GRANT, REVOKE, OPTIMIZE, CREATE|ALTER|DROP FUNCTION|PROCEDURE,
* CREATE SPFUNCTION, INSTALL|UNINSTALL PLUGIN
*/
if (is_log_table_write_query(lex->sql_command) ||
is_update_query(lex->sql_command))
{
if (thd->variables.sql_log_bin == 0 &&
force_data_modify_op_replication)
{
type |= QUERY_TYPE_GLOBAL_WRITE;
}
else if (lex->option_type == OPT_SESSION)
{
type |= QUERY_TYPE_SESSION_WRITE;
type |= QUERY_TYPE_SESSION_WRITE;
} else {
type |= QUERY_TYPE_WRITE;
}
goto return_qtype;
}
/** Try to catch session modifications here */
switch (lex->sql_command) {
case SQLCOM_SET_OPTION:
case SQLCOM_SET_OPTION: /*< SET commands. */
if (lex->option_type == OPT_GLOBAL)
{
type |= QUERY_TYPE_GLOBAL_WRITE;
@ -672,6 +671,7 @@ static bool skygw_stmt_causes_implicit_commit(LEX* lex, uint mask)
succp = lex->autocommit ? true : false;
break;
default:
succp = true;
break;
}

View File

@ -670,6 +670,13 @@ static int routeQuery(
"Packet type\t%s",
STRPACKETTYPE(packet_type))));
if (QUERY_IS_TYPE(qtype,QUERY_TYPE_COMMIT) &&
transaction_active)
{
transaction_active = false;
}
switch (qtype) {
case QUERY_TYPE_WRITE:
LOGIF(LT, (skygw_log_write(
@ -724,12 +731,6 @@ static int routeQuery(
break;
case QUERY_TYPE_SESSION_WRITE:
case (QUERY_TYPE_SESSION_WRITE|QUERY_TYPE_COMMIT):
if (QUERY_IS_TYPE(qtype,QUERY_TYPE_COMMIT) &&
transaction_active)
{
transaction_active = false;
}
/**
* Execute in backends used by current router session.
* Save session variable commands to router session property

View File

@ -30,7 +30,7 @@ runtests:
@echo $(shell date) >> $(TESTLOG)
@echo "Test MaxScale R/W Split" >> $(TESTLOG)
@echo "-------------------------------" >> $(TESTLOG)
./rwsplit.sh $(TESTLOG) $(THOST) $(TPORT_RW) $(TMASTER_ID) $(TUSER) $(TPWD)
./rwsplit.sh $(TESTLOG) $(THOST) $(TPORT_RW) $(TMASTER_ID) $(TUSER) $(TPWD)
@echo "" >> $(TESTLOG)

View File

@ -49,3 +49,67 @@ if [ "$a" != "$TRETVAL" ]; then
else
echo "$TINPUT PASSED">>$TLOG ;
fi
TINPUT=test_implicit_commit1.sql
TRETVAL=$TMASTER_ID
a=`$RUNCMD < ./$TINPUT`
if [ "$a" == "$TRETVAL" ]; then
echo "$TINPUT FAILED, return value $a when it was not accetable">>$TLOG;
else
echo "$TINPUT PASSED">>$TLOG ;
fi
TINPUT=test_implicit_commit2.sql
TRETVAL=$TMASTER_ID
a=`$RUNCMD < ./$TINPUT`
if [ "$a" == "$TRETVAL" ]; then
echo "$TINPUT FAILED, return value $a when it was not accetable">>$TLOG;
else
echo "$TINPUT PASSED">>$TLOG ;
fi
TINPUT=test_implicit_commit3.sql
TRETVAL=$TMASTER_ID
a=`$RUNCMD < ./$TINPUT`
if [ "$a" == "$TRETVAL" ]; then
echo "$TINPUT FAILED, return value $a when it was not accetable">>$TLOG;
else
echo "$TINPUT PASSED">>$TLOG ;
fi
TINPUT=test_implicit_commit4.sql
TRETVAL=$TMASTER_ID
a=`$RUNCMD < ./$TINPUT`
if [ "$a" != "$TRETVAL" ]; then
echo "$TINPUT FAILED, return value $a when $TRETVAL was expected">>$TLOG;
else
echo "$TINPUT PASSED">>$TLOG ;
fi
TINPUT=test_implicit_commit5.sql
TRETVAL=$TMASTER_ID
a=`$RUNCMD < ./$TINPUT`
if [ "$a" == "$TRETVAL" ]; then
echo "$TINPUT FAILED, return value $a when it was not accetable">>$TLOG;
else
echo "$TINPUT PASSED">>$TLOG ;
fi
TINPUT=test_implicit_commit6.sql
TRETVAL=$TMASTER_ID
a=`$RUNCMD < ./$TINPUT`
if [ "$a" == "$TRETVAL" ]; then
echo "$TINPUT FAILED, return value $a when it was not accetable">>$TLOG;
else
echo "$TINPUT PASSED">>$TLOG ;
fi
TINPUT=test_implicit_commit7.sql
TRETVAL=$TMASTER_ID
a=`$RUNCMD < ./$TINPUT`
if [ "$a" == "$TRETVAL" ]; then
echo "$TINPUT FAILED, return value $a when it was not accetable">>$TLOG;
else
echo "$TINPUT PASSED">>$TLOG ;
fi

View File

@ -0,0 +1,8 @@
DROP DATABASE If EXISTS FOO;
SET autocommit=0;
BEGIN;
CREATE DATABASE FOO; -- implicit commit
SELECT (@@server_id) INTO @a;
SELECT @a; --should read from slave
DROP DATABASE If EXISTS FOO;
COMMIT;

View File

@ -0,0 +1,15 @@
USE test;
DROP TABLE IF EXISTS T1;
DROP EVENT IF EXISTS myevent;
SET autocommit=0;
BEGIN;
CREATE TABLE T1 (id integer);
CREATE EVENT myevent
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR
DO
UPDATE t1 SET id = id + 1;
SELECT (@@server_id) INTO @a;
SELECT @a; --should read from slave
DROP TABLE IF EXISTS T1;
DROP EVENT IF EXISTS myevent;
COMMIT;

View File

@ -0,0 +1,9 @@
USE test;
DROP TABLE IF EXISTS T1;
SET autocommit=0;
BEGIN;
CREATE TABLE T1 (id integer); -- implicit commit
SELECT (@@server_id) INTO @a;
SELECT @a; --should read from slave
DROP TABLE IF EXISTS T1;
COMMIT;

View File

@ -0,0 +1,9 @@
USE test;
DROP TABLE IF EXISTS T1;
SET autocommit=0;
BEGIN;
CREATE TEMPORARY TABLE T1 (id integer); -- NO implicit commit
SELECT (@@server_id) INTO @a;
SELECT @a; --should read from master
DROP TABLE IF EXISTS T1;
COMMIT;

View File

@ -0,0 +1,14 @@
USE test;
DROP PROCEDURE IF EXISTS simpleproc;
SET autocommit=0;
BEGIN;
DELIMITER //
CREATE PROCEDURE simpleproc (OUT param1 INT)
BEGIN
SELECT COUNT(*) INTO param1 FROM t;
END //
DELIMITER ;
SELECT (@@server_id) INTO @a;
SELECT @a; --should read from slave
DROP PROCEDURE IF EXISTS simpleproc;
COMMIT;

View File

@ -0,0 +1,11 @@
USE test;
DROP FUNCTION IF EXISTS hello;
SET autocommit=0;
BEGIN;
CREATE FUNCTION hello (s CHAR(20))
RETURNS CHAR(50) DETERMINISTIC
RETURN CONCAT('Hello, ',s,'!'); -- implicit COMMIT
SELECT (@@server_id) INTO @a;
SELECT @a; --should read from slave
DROP FUNCTION IF EXISTS hello;
COMMIT;

View File

@ -0,0 +1,10 @@
USE test;
DROP TABLE IF EXISTS T1;
CREATE TABLE T1 (id integer); -- implicit commit
SET autocommit=0;
BEGIN;
CREATE INDEX foo_t1 on T1 (id); -- implicit commit
SELECT (@@server_id) INTO @a;
SELECT @a; --should read from slave
DROP TABLE IF EXISTS T1;
COMMIT;