Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/5.5-galera' into 10.0-galera
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan Lindström committed Aug 2, 2018
2 parents c5a8583 + e88e26b commit 9b29bda
Show file tree
Hide file tree
Showing 6 changed files with 369 additions and 98 deletions.
111 changes: 111 additions & 0 deletions mysql-test/suite/galera/r/mysql-wsrep#332.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER) ENGINE=INNODB;
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1);
INSERT INTO c VALUES (2, 2);
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p SET f1 = f1 + 100;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
ALTER TABLE c ADD FOREIGN KEY (p_id) REFERENCES p(f1);
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
COMMIT;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT * FROM p;
f1 f2
1 0
2 0
SELECT * FROM c;
f1 p_id
1 1
2 2
DROP TABLE c;
DROP TABLE p;
CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id1 INTEGER, p_id2 INTEGER) ENGINE=INNODB;
INSERT INTO p1 VALUES (1, 0), (2, 0);
INSERT INTO p2 VALUES (1, 0), (2, 0);
INSERT INTO c VALUES (1, 1, 1);
INSERT INTO c VALUES (2, 2, 2);
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p1 SET f1 = f1 + 100;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
ALTER TABLE c ADD FOREIGN KEY (p_id1) REFERENCES p1(f1), ADD FOREIGN KEY (p_id2) REFERENCES p2(f1);
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
COMMIT;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT * FROM p1;
f1 f2
1 0
2 0
SELECT * FROM p2;
f1 f2
1 0
2 0
SELECT * FROM c;
f1 p_id1 p_id2
1 1 1
2 2 2
DROP TABLE c;
DROP TABLE p1;
DROP TABLE p2;
CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id1 INTEGER, p_id2 INTEGER) ENGINE=INNODB;
INSERT INTO p1 VALUES (1, 0), (2, 0);
INSERT INTO p2 VALUES (1, 0), (2, 0);
INSERT INTO c VALUES (1, 1, 1);
INSERT INTO c VALUES (2, 2, 2);
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p2 SET f1 = f1 + 100;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
ALTER TABLE c ADD FOREIGN KEY (p_id1) REFERENCES p1(f1), ADD FOREIGN KEY (p_id2) REFERENCES p2(f1);
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'dbug=';
SET GLOBAL wsrep_provider_options = 'dbug=d,local_monitor_enter_sync';
COMMIT;
SET SESSION wsrep_on = 0;
SET SESSION wsrep_on = 1;
SET GLOBAL wsrep_provider_options = 'signal=apply_monitor_slave_enter_sync';
SET GLOBAL wsrep_provider_options = 'signal=local_monitor_enter_sync';
SET GLOBAL wsrep_provider_options = 'dbug=';
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
SELECT * FROM p1;
f1 f2
1 0
2 0
SELECT * FROM p2;
f1 f2
1 0
2 0
SELECT * FROM c;
f1 p_id1 p_id2
1 1 1
2 2 2
DROP TABLE c;
DROP TABLE p1;
DROP TABLE p2;
113 changes: 113 additions & 0 deletions mysql-test/suite/galera/t/mysql-wsrep#332.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_debug_sync.inc
--source suite/galera/include/galera_have_debug_sync.inc

# Open connection node_1a here, MW-369.inc will use it later
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1

#
# Test the scenario where a foreign key is added to an existing child table, and
# concurrently UPDATE the parent table so that it violates the constraint.
#
# We expect that ALTER TABLE ADD FOREIGN KEY adds a table level key on both
# parent and child table. And therefore we also expect the UPDATE to fail
# certification.
#
--connection node_1
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER) ENGINE=INNODB;

INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);

INSERT INTO c VALUES (1, 1);
INSERT INTO c VALUES (2, 2);

--let $mw_369_parent_query = UPDATE p SET f1 = f1 + 100
--let $mw_369_child_query = ALTER TABLE c ADD FOREIGN KEY (p_id) REFERENCES p(f1)

--source MW-369.inc

# Expect certification failure
--connection node_1
--error ER_LOCK_DEADLOCK
--reap

--connection node_2
SELECT * FROM p;
SELECT * FROM c;

DROP TABLE c;
DROP TABLE p;


#
# Same as above, except that two foreign keys pointing to different parent
# tables are added, p1 and p2. Concurrently UPDATE p1.
#
# Expect certification error on UPDATE.
#
--connection node_1
CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id1 INTEGER, p_id2 INTEGER) ENGINE=INNODB;

INSERT INTO p1 VALUES (1, 0), (2, 0);
INSERT INTO p2 VALUES (1, 0), (2, 0);

INSERT INTO c VALUES (1, 1, 1);
INSERT INTO c VALUES (2, 2, 2);

--let $mw_369_parent_query = UPDATE p1 SET f1 = f1 + 100
--let $mw_369_child_query = ALTER TABLE c ADD FOREIGN KEY (p_id1) REFERENCES p1(f1), ADD FOREIGN KEY (p_id2) REFERENCES p2(f1)

--source MW-369.inc

# Expect certification failure
--connection node_1
--error ER_LOCK_DEADLOCK
--reap

--connection node_2
SELECT * FROM p1;
SELECT * FROM p2;
SELECT * FROM c;

DROP TABLE c;
DROP TABLE p1;
DROP TABLE p2;


#
# Same as above, except that UPDATE is on p2.
#
--connection node_1
CREATE TABLE p1 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE p2 (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id1 INTEGER, p_id2 INTEGER) ENGINE=INNODB;

INSERT INTO p1 VALUES (1, 0), (2, 0);
INSERT INTO p2 VALUES (1, 0), (2, 0);

INSERT INTO c VALUES (1, 1, 1);
INSERT INTO c VALUES (2, 2, 2);

--let $mw_369_parent_query = UPDATE p2 SET f1 = f1 + 100
--let $mw_369_child_query = ALTER TABLE c ADD FOREIGN KEY (p_id1) REFERENCES p1(f1), ADD FOREIGN KEY (p_id2) REFERENCES p2(f1)

--source MW-369.inc

# Expect certification failure
--connection node_1
--error ER_LOCK_DEADLOCK
--reap

--connection node_2
SELECT * FROM p1;
SELECT * FROM p2;
SELECT * FROM c;

DROP TABLE c;
DROP TABLE p1;
DROP TABLE p2;
17 changes: 12 additions & 5 deletions sql/sql_alter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,13 @@ bool Sql_cmd_alter_table::execute(THD *thd)
if ((!thd->is_current_stmt_binlog_format_row() ||
!find_temporary_table(thd, first_table)))
{
WSREP_TO_ISOLATION_BEGIN(((lex->name.str) ? select_lex->db : NULL),
((lex->name.str) ? lex->name.str : NULL),
first_table);
WSREP_TO_ISOLATION_BEGIN_ALTER(((lex->name.str) ? select_lex->db : NULL),
((lex->name.str) ? lex->name.str : NULL),
first_table,
&alter_info);

thd->variables.auto_increment_offset = 1;
thd->variables.auto_increment_increment = 1;
}
#endif /* WITH_WSREP */
result= mysql_alter_table(thd, select_lex->db, lex->name.str,
Expand All @@ -326,10 +330,13 @@ bool Sql_cmd_alter_table::execute(THD *thd)

DBUG_RETURN(result);

DBUG_RETURN(result);
#ifdef WITH_WSREP
error:
WSREP_WARN("ALTER TABLE isolation failure");
DBUG_RETURN(TRUE);
{
WSREP_WARN("ALTER TABLE isolation failure");
DBUG_RETURN(TRUE);
}
#endif /* WITH_WSREP */
}

Expand Down
5 changes: 5 additions & 0 deletions sql/sql_parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@ inline bool is_supported_parser_charset(CHARSET_INFO *cs)
#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \
if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto error;

#define WSREP_TO_ISOLATION_BEGIN_ALTER(db_, table_, table_list_, alter_info_) \
if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, \
table_list_, alter_info_)) \
goto error;

#define WSREP_TO_ISOLATION_END \
if (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER)) \
wsrep_to_isolation_end(thd);
Expand Down
Loading

0 comments on commit 9b29bda

Please sign in to comment.