Commit 4cfef2a5 authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.2 into bb-10.2-ext

parents fe949504 429ca9a8
connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection node_1;
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, f2 INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1) ON DELETE CASCADE);
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1, 0);
connection node_1a;
connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE c SET f2=1 where f1=1;
connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
DELETE FROM p WHERE f1 = 1;
connection node_1a;
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';
connection node_1;
COMMIT;
connection node_1a;
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=';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_2;
SELECT * FROM p;
f1 f2
2 0
SELECT * FROM c;
f1 p_id f2
DROP TABLE c;
DROP TABLE p;
connection node_1;
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, f2 INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1) ON UPDATE CASCADE);
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1, 0);
connection node_1a;
connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE c SET f2=2 where f1=1;
connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
UPDATE p set f1=11 WHERE f1 = 1;
connection node_1a;
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';
connection node_1;
COMMIT;
connection node_1a;
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=';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_2;
SELECT * FROM p;
f1 f2
2 0
11 0
SELECT * FROM c;
f1 p_id f2
1 11 0
DROP TABLE c;
DROP TABLE p;
connection node_1;
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, f2 INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1) ON UPDATE CASCADE);
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1, 0);
connection node_1a;
connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE c SET p_id=2 where f1=1;
connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
UPDATE p set f1=11 WHERE f1 = 1;
connection node_1a;
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';
connection node_1;
COMMIT;
connection node_1a;
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=';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_2;
SELECT * FROM p;
f1 f2
2 0
11 0
SELECT * FROM c;
f1 p_id f2
1 11 0
connection node_1a;
connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p set f1=21 WHERE f1 = 11;
connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
UPDATE c SET p_id=2 where f1=1;
connection node_1a;
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';
connection node_1;
COMMIT;
connection node_1a;
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=';
connection node_1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
connection node_2;
SELECT * FROM p;
f1 f2
2 0
11 0
SELECT * FROM c;
f1 p_id f2
1 2 0
DROP TABLE c;
DROP TABLE p;
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, p1_id INTEGER, p2_id INTEGER, f2 INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1) ON DELETE CASCADE,
CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1));
INSERT INTO p1 VALUES (1, 0);
INSERT INTO p2 VALUES (1, 0);
INSERT INTO c VALUES (1, 1, 1, 0);
connection node_1a;
connection node_1;
SET AUTOCOMMIT=ON;
START TRANSACTION;
UPDATE p2 SET f2=2 where f1=1;
connection node_1a;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options = 'dbug=d,apply_monitor_slave_enter_sync';
connection node_2;
DELETE FROM p1 WHERE f1 = 1;
connection node_1a;
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';
connection node_1;
COMMIT;
connection node_1a;
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=';
connection node_1;
connection node_2;
SELECT * FROM p1;
f1 f2
SELECT * FROM p2;
f1 f2
1 2
SELECT * FROM c;
f1 p1_id p2_id f2
DROP TABLE c,p1,p2;
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source suite/galera/include/galera_have_debug_sync.inc
#
# we must open connection node_1a here, MW-369.inc will use it later
#
--connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1
#
# cascading delete operation is replicated from node2
# and this conflicts with an update for child table in node1
#
# As a result, the update should fail for certification error
#
--connection node_1
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, f2 INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1) ON DELETE CASCADE);
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1, 0);
--let $mw_369_parent_query = UPDATE c SET f2=1 where f1=1
--let $mw_369_child_query = DELETE FROM p WHERE f1 = 1
--connection node_1a
--source MW-369.inc
# Commit fails
--connection node_1
--error ER_LOCK_DEADLOCK
--reap
--connection node_2
SELECT * FROM p;
SELECT * FROM c;
DROP TABLE c;
DROP TABLE p;
#
# cascading update operation is replicated from node2
# and this conflicts with an update for child table in node1
#
# As a result, the update should fail for certification error
#
--connection node_1
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, f2 INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1) ON UPDATE CASCADE);
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1, 0);
--let $mw_369_parent_query = UPDATE c SET f2=2 where f1=1
--let $mw_369_child_query = UPDATE p set f1=11 WHERE f1 = 1
--connection node_1a
--source MW-369.inc
# Commit fails
--connection node_1
--error ER_LOCK_DEADLOCK
--reap
--connection node_2
SELECT * FROM p;
SELECT * FROM c;
DROP TABLE c;
DROP TABLE p;
#
# ON UPDATE CASCADE tests
# Here we update primary key of parent table to cause cascaded update
# on child table
#
# cascading update operation is replicated from node2
# and this conflicts with an update for child table in node1
#
# As a result, the update should fail for certification error
#
--connection node_1
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
CREATE TABLE c (f1 INTEGER PRIMARY KEY, p_id INTEGER, f2 INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES p (f1) ON UPDATE CASCADE);
INSERT INTO p VALUES (1, 0);
INSERT INTO p VALUES (2, 0);
INSERT INTO c VALUES (1, 1, 0);
--let $mw_369_parent_query = UPDATE c SET p_id=2 where f1=1
--let $mw_369_child_query = UPDATE p set f1=11 WHERE f1 = 1
--connection node_1a
--source MW-369.inc
# Commit fails
--connection node_1
--error ER_LOCK_DEADLOCK
--reap
# same as previous, but statements in different order
--connection node_2
SELECT * FROM p;
SELECT * FROM c;
--let $mw_369_parent_query = UPDATE p set f1=21 WHERE f1 = 11
--let $mw_369_child_query = UPDATE c SET p_id=2 where f1=1
--connection node_1a
--source MW-369.inc
# Commit fails
--connection node_1
--error ER_LOCK_DEADLOCK
--reap
--connection node_2
SELECT * FROM p;
SELECT * FROM c;
DROP TABLE c;
DROP TABLE p;
#
# CASCADE DELETE tests with two parent tables
# Here we cause cascaded operation on child table through
# one parent table and have other operation on the other
# parent table
#
# cascading update operation is replicated from node2
# but this does not conflict with an update for the other parent table in node1
#
# As a result, the update on p2 should succeed
#
--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, p1_id INTEGER, p2_id INTEGER, f2 INTEGER,
CONSTRAINT fk_1 FOREIGN KEY (p1_id) REFERENCES p1 (f1) ON DELETE CASCADE,
CONSTRAINT fk_2 FOREIGN KEY (p2_id) REFERENCES p2 (f1));
INSERT INTO p1 VALUES (1, 0);
INSERT INTO p2 VALUES (1, 0);
INSERT INTO c VALUES (1, 1, 1, 0);
--let $mw_369_parent_query = UPDATE p2 SET f2=2 where f1=1
--let $mw_369_child_query = DELETE FROM p1 WHERE f1 = 1
--connection node_1a
--source MW-369.inc
# Commit succeeds
--connection node_1
--reap
# same as previous, but statements in different order
--connection node_2
SELECT * FROM p1;
SELECT * FROM p2;
SELECT * FROM c;
DROP TABLE c,p1,p2;
...@@ -23,13 +23,13 @@ use Fcntl 'SEEK_CUR', 'SEEK_END'; ...@@ -23,13 +23,13 @@ use Fcntl 'SEEK_CUR', 'SEEK_END';
my $page_size = $ENV{'INNODB_PAGE_SIZE'}; my $page_size = $ENV{'INNODB_PAGE_SIZE'};
my $restart; my $restart;
open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}ibdata1") or die;
if ($ENV{'MYSQLD_IS_DEBUG'}) if ($ENV{'MYSQLD_IS_DEBUG'})
{ {
# It is impractical to ensure that CREATE TABLE t will extend ibdata1. # It is impractical to ensure that CREATE TABLE t will extend ibdata1.
# We rely on innodb_system_tablespace_extend_debug=1 # We rely on innodb_system_tablespace_extend_debug=1
# to recover from this fault injection if no size change was redo-logged. # to recover from this fault injection if no size change was redo-logged.
my $root = $ENV{'INNODB_ROOT_PAGE'}; my $root = $ENV{'INNODB_ROOT_PAGE'};
open(FILE, "+<", "$ENV{'MYSQLD_DATADIR'}ibdata1") or die;
my $size = sysseek(FILE, 0, SEEK_END) / $page_size; my $size = sysseek(FILE, 0, SEEK_END) / $page_size;
seek(FILE, $page_size * ($root + 1), SEEK_SET) or die; seek(FILE, $page_size * ($root + 1), SEEK_SET) or die;
my $empty_tail= 1; my $empty_tail= 1;
...@@ -39,8 +39,22 @@ if ($ENV{'MYSQLD_IS_DEBUG'}) ...@@ -39,8 +39,22 @@ if ($ENV{'MYSQLD_IS_DEBUG'})
$restart = "--innodb-data-file-size-debug=$size"; $restart = "--innodb-data-file-size-debug=$size";
truncate(FILE, $page_size * $root); truncate(FILE, $page_size * $root);
} }
close FILE;
} }
# Clear the doublewrite buffer entries for our tables.
sysseek(FILE, 6 * $page_size - 190, 0)||die "Unable to seek ibdata1\n";
sysread(FILE, $_, 12) == 12||die "Unable to read TRX_SYS\n";
my($magic,$d1,$d2)=unpack "NNN", $_;
die "magic=$magic, $d1, $d2\n" unless $magic == 536853855 && $d2 >= $d1 + 64;
sysseek(FILE, $d1 * $page_size, 0)||die "Unable to seek ibdata1\n";
# Find the pages in the doublewrite buffer
for (my $d = $d1; $d < $d2 + 64; $d++) {
sysread(FILE, $_, $page_size)==$page_size||die "Cannot read doublewrite\n";
my($space_id,$offset)=unpack "x[4]Nx[26]N",$_;
next unless $space_id && $offset > 3;
sysseek(FILE, $d * $page_size, 0)||die "Unable to seek ibdata1\n";
syswrite(FILE, chr(0) x $page_size)==$page_size||die;
}
close FILE;
open(FILE, ">$ENV{MYSQLTEST_VARDIR}/log/start_mysqld.txt") || die; open(FILE, ">$ENV{MYSQLTEST_VARDIR}/log/start_mysqld.txt") || die;
print FILE "--let \$restart_parameters=$restart\n" if $restart; print FILE "--let \$restart_parameters=$restart\n" if $restart;
print FILE "--source include/start_mysqld.inc\n"; print FILE "--source include/start_mysqld.inc\n";
......
...@@ -539,6 +539,7 @@ wsrep_run_wsrep_commit(THD *thd, bool all) ...@@ -539,6 +539,7 @@ wsrep_run_wsrep_commit(THD *thd, bool all)
break; break;
case WSREP_BF_ABORT: case WSREP_BF_ABORT:
DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED); DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED);
/* fall through */
case WSREP_TRX_FAIL: case WSREP_TRX_FAIL:
WSREP_DEBUG("commit failed for reason: %d", rcode); WSREP_DEBUG("commit failed for reason: %d", rcode);
DBUG_PRINT("wsrep", ("replicating commit fail")); DBUG_PRINT("wsrep", ("replicating commit fail"));
......
...@@ -1442,8 +1442,7 @@ row_ins_foreign_check_on_constraint( ...@@ -1442,8 +1442,7 @@ row_ins_foreign_check_on_constraint(
foreign, foreign,
clust_rec, clust_rec,
clust_index, clust_index,
FALSE, FALSE, FALSE);
(node) ? TRUE : FALSE);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
fprintf(stderr, fprintf(stderr,
"WSREP: foreign key append failed: %d\n", err); "WSREP: foreign key append failed: %d\n", err);
......
...@@ -460,19 +460,18 @@ wsrep_row_upd_check_foreign_constraints( ...@@ -460,19 +460,18 @@ wsrep_row_upd_check_foreign_constraints(
@param[in] node query node @param[in] node query node
@param[in] trx transaction @param[in] trx transaction
@return whether the node cannot be ignored */ @return whether the node cannot be ignored */
static inline
bool bool
wsrep_must_process_fk(const upd_node_t* node, const trx_t* trx) wsrep_must_process_fk(const upd_node_t* node, const trx_t* trx)
{ {
if (que_node_get_type(node->common.parent) != QUE_NODE_UPDATE if (que_node_get_type(node->common.parent) != QUE_NODE_UPDATE ||
|| !wsrep_on(trx->mysql_thd)) { !wsrep_on(trx->mysql_thd)) {
return false; return false;
} }
const upd_cascade_t& nodes = *static_cast<const upd_node_t*>( const upd_node_t* parent = static_cast<const upd_node_t*>(node->common.parent);
node->common.parent)->cascade_upd_nodes;
const upd_cascade_t::const_iterator end = nodes.end(); return parent->cascade_upd_nodes->empty();
return std::find(nodes.begin(), end, node) == end;
} }
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
...@@ -2443,6 +2442,7 @@ row_upd_sec_index_entry( ...@@ -2443,6 +2442,7 @@ row_upd_sec_index_entry(
if (!referenced && foreign if (!referenced && foreign
&& wsrep_must_process_fk(node, trx) && wsrep_must_process_fk(node, trx)
&& !wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { && !wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
ulint* offsets = rec_get_offsets( ulint* offsets = rec_get_offsets(
rec, index, NULL, ULINT_UNDEFINED, rec, index, NULL, ULINT_UNDEFINED,
&heap); &heap);
...@@ -2749,6 +2749,9 @@ row_upd_clust_rec_by_insert( ...@@ -2749,6 +2749,9 @@ row_upd_clust_rec_by_insert(
} }
#ifdef WITH_WSREP #ifdef WITH_WSREP
} else if (foreign && wsrep_must_process_fk(node, trx)) { } else if (foreign && wsrep_must_process_fk(node, trx)) {
err = wsrep_row_upd_check_foreign_constraints(
node, pcur, table, index, offsets, thr, mtr);
switch (err) { switch (err) {
case DB_SUCCESS: case DB_SUCCESS:
case DB_NO_REFERENCED_ROW: case DB_NO_REFERENCED_ROW:
...@@ -2760,16 +2763,11 @@ row_upd_clust_rec_by_insert( ...@@ -2760,16 +2763,11 @@ row_upd_clust_rec_by_insert(
<< " index " << index->name << " index " << index->name
<< " table " << index->table->name; << " table " << index->table->name;
} }
break; goto err_exit;
default: default:
ib::error() << "WSREP: referenced FK check fail: " << ut_strerr(err) ib::error() << "WSREP: referenced FK check fail: " << ut_strerr(err)
<< " index " << index->name << " index " << index->name
<< " table " << index->table->name; << " table " << index->table->name;
break;
}
if (err != DB_SUCCESS) {
goto err_exit; goto err_exit;
} }
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
...@@ -2956,6 +2954,7 @@ row_upd_del_mark_clust_rec( ...@@ -2956,6 +2954,7 @@ row_upd_del_mark_clust_rec(
dberr_t err; dberr_t err;
rec_t* rec; rec_t* rec;
trx_t* trx = thr_get_trx(thr); trx_t* trx = thr_get_trx(thr);
ut_ad(node); ut_ad(node);
ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(index));
ut_ad(node->is_delete); ut_ad(node->is_delete);
...@@ -2988,6 +2987,7 @@ row_upd_del_mark_clust_rec( ...@@ -2988,6 +2987,7 @@ row_upd_del_mark_clust_rec(
} else if (foreign && wsrep_must_process_fk(node, trx)) { } else if (foreign && wsrep_must_process_fk(node, trx)) {
err = wsrep_row_upd_check_foreign_constraints( err = wsrep_row_upd_check_foreign_constraints(
node, pcur, index->table, index, offsets, thr, mtr); node, pcur, index->table, index, offsets, thr, mtr);
switch (err) { switch (err) {
case DB_SUCCESS: case DB_SUCCESS:
case DB_NO_REFERENCED_ROW: case DB_NO_REFERENCED_ROW:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment