summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2021-07-19 22:17:51 +0300
committerAleksey Midenkov <midenok@gmail.com>2021-08-18 13:36:49 +0300
commit1b45e05ccefc6a00513516b8bc0fb41a42d1b695 (patch)
tree597c5f501de0e4ea7b362df983af7b2c659ff521
parentdc3a350df665b8e9bddc96365cec23a525f6b0b4 (diff)
downloadmariadb-git-1b45e05ccefc6a00513516b8bc0fb41a42d1b695.tar.gz
MDEV-21555 Assertion secondary index is out of sync on delete from versioned table
Delete-marked record is on the secondary index and the clustered index already purged the corresponding record. We cannot detect if such record is historical and we should not: the algorithm of row_ins_check_foreign_constraint() skips such record anyway.
-rw-r--r--mysql-test/suite/versioning/r/foreign.result13
-rw-r--r--mysql-test/suite/versioning/t/foreign.test18
-rw-r--r--storage/innobase/row/row0ins.cc34
3 files changed, 48 insertions, 17 deletions
diff --git a/mysql-test/suite/versioning/r/foreign.result b/mysql-test/suite/versioning/r/foreign.result
index e54afdbc74e..d157916c60c 100644
--- a/mysql-test/suite/versioning/r/foreign.result
+++ b/mysql-test/suite/versioning/r/foreign.result
@@ -443,3 +443,16 @@ pk f1 f2 left(f3, 4) check_row_ts(row_start, row_end)
1 8 8 SHOR HISTORICAL ROW
2 8 8 LONG HISTORICAL ROW
drop table t1;
+#
+# MDEV-21555 Assertion secondary index is out of sync on delete from versioned table
+#
+create table t1 (a int, b int as (a + 1) virtual, key(a)) engine=innodb with system versioning;
+set foreign_key_checks= off;
+insert into t1 (a) values (1), (2);
+alter table t1 add foreign key (b) references t1 (a), algorithm=copy;
+update t1 set a= null where a = 1;
+delete from t1 where a is null;
+set foreign_key_checks= on;
+delete history from t1;
+delete from t1;
+drop table t1;
diff --git a/mysql-test/suite/versioning/t/foreign.test b/mysql-test/suite/versioning/t/foreign.test
index 725f51f0660..1c834719e0f 100644
--- a/mysql-test/suite/versioning/t/foreign.test
+++ b/mysql-test/suite/versioning/t/foreign.test
@@ -476,4 +476,22 @@ select pk, f1, f2, left(f3, 4), check_row_ts(row_start, row_end) from t1 for sys
# cleanup
drop table t1;
+--echo #
+--echo # MDEV-21555 Assertion secondary index is out of sync on delete from versioned table
+--echo #
+create table t1 (a int, b int as (a + 1) virtual, key(a)) engine=innodb with system versioning;
+
+set foreign_key_checks= off;
+insert into t1 (a) values (1), (2);
+alter table t1 add foreign key (b) references t1 (a), algorithm=copy;
+update t1 set a= null where a = 1;
+delete from t1 where a is null;
+set foreign_key_checks= on;
+
+delete history from t1;
+delete from t1;
+
+# cleanup
+drop table t1;
+
--source suite/versioning/common_finish.inc
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 380ef7def31..ae105743d45 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -1666,23 +1666,6 @@ row_ins_check_foreign_constraint(
cmp = cmp_dtuple_rec(entry, rec, offsets);
if (cmp == 0) {
- if (check_table->versioned()) {
- bool history_row = false;
-
- if (check_index->is_primary()) {
- history_row = check_index->
- vers_history_row(rec, offsets);
- } else if (check_index->
- vers_history_row(rec, history_row))
- {
- break;
- }
-
- if (history_row) {
- continue;
- }
- }
-
if (rec_get_deleted_flag(rec,
rec_offs_comp(offsets))) {
/* In delete-marked records, DB_TRX_ID must
@@ -1704,6 +1687,23 @@ row_ins_check_foreign_constraint(
goto end_scan;
}
} else {
+ if (check_table->versioned()) {
+ bool history_row = false;
+
+ if (check_index->is_primary()) {
+ history_row = check_index->
+ vers_history_row(rec,
+ offsets);
+ } else if (check_index->
+ vers_history_row(rec,
+ history_row)) {
+ break;
+ }
+
+ if (history_row) {
+ continue;
+ }
+ }
/* Found a matching record. Lock only
a record because we can allow inserts
into gaps */