summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-03-09 11:32:31 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2020-03-09 11:38:34 +0200
commitadb411763119873e37176015a97d749ad531240a (patch)
tree6a82bdf077cee2295e254a7a3383611536d40dc2
parent57c592f74dfbf2350519bc6fa1e0a61e888fa151 (diff)
downloadmariadb-git-adb411763119873e37176015a97d749ad531240a.tar.gz
MDEV-21892: Assertion ...row_get_rec_trx_id... failed on SELECT
btr_cur_upd_rec_in_place(): Invoke page_zip_rec_set_deleted() for ROW_FORMAT=COMPRESSED pages, so that the change will be written to the redo log. This part of crash recovery was broken in commit 08ba388713946c03aa591899cd3a446a6202f882 (MDEV-12353).
-rw-r--r--mysql-test/suite/innodb_zip/r/recover.result17
-rw-r--r--mysql-test/suite/innodb_zip/t/recover.test16
-rw-r--r--storage/innobase/btr/btr0cur.cc23
3 files changed, 47 insertions, 9 deletions
diff --git a/mysql-test/suite/innodb_zip/r/recover.result b/mysql-test/suite/innodb_zip/r/recover.result
index b7452655268..fddb070538d 100644
--- a/mysql-test/suite/innodb_zip/r/recover.result
+++ b/mysql-test/suite/innodb_zip/r/recover.result
@@ -1,3 +1,14 @@
+FLUSH TABLES;
+#
+# MDEV-21892 Assertion 'index != clust_index || row_get_rec_trx_id()'
+#
+connect con1,localhost,root;
+CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPRESSED;
+INSERT INTO t1 VALUES (1),(2);
+BEGIN;
+UPDATE t1 SET pk=1;
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+connection default;
#
# MDEV-12720 recovery fails with "Generic error"
# for ROW_FORMAT=compressed
@@ -12,6 +23,12 @@ insert into a select null, uuid() from a a, a b, a c;
SET GLOBAL innodb_flush_log_at_trx_commit=1;
COMMIT;
# restart
+disconnect con1;
+SELECT * FROM t1;
+pk
+1
+2
+DROP TABLE t1;
SELECT COUNT(*) from a;
COUNT(*)
1010
diff --git a/mysql-test/suite/innodb_zip/t/recover.test b/mysql-test/suite/innodb_zip/t/recover.test
index f32ff3d3783..194ef10a8ef 100644
--- a/mysql-test/suite/innodb_zip/t/recover.test
+++ b/mysql-test/suite/innodb_zip/t/recover.test
@@ -1,12 +1,21 @@
--source include/innodb_page_size_small.inc
--source include/not_embedded.inc
---disable_query_log
# This test kills the server, which could corrupt some mysql.* tables
# that are not created with ENGINE=InnoDB.
# Flush any non-InnoDB tables to prevent that from happening.
FLUSH TABLES;
---enable_query_log
+
+--echo #
+--echo # MDEV-21892 Assertion 'index != clust_index || row_get_rec_trx_id()'
+--echo #
+connect (con1,localhost,root);
+CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPRESSED;
+INSERT INTO t1 VALUES (1),(2);
+BEGIN;
+--error ER_DUP_ENTRY
+UPDATE t1 SET pk=1;
+connection default;
--echo #
--echo # MDEV-12720 recovery fails with "Generic error"
@@ -25,6 +34,9 @@ COMMIT;
--let $shutdown_timeout=0
--source include/restart_mysqld.inc
+disconnect con1;
+SELECT * FROM t1;
+DROP TABLE t1;
SELECT COUNT(*) from a;
DROP TABLE a;
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index fbb2fbe9b5d..7e9be0c1a92 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -4110,16 +4110,25 @@ void btr_cur_upd_rec_in_place(rec_t *rec, const dict_index_t *index,
}
#endif /* UNIV_DEBUG */
- byte* info_bits = &rec[rec_offs_comp(offsets)
- ? -REC_NEW_INFO_BITS
- : -REC_OLD_INFO_BITS];
- compile_time_assert(REC_INFO_BITS_SHIFT == 0);
- if ((*info_bits & REC_INFO_BITS_MASK) == update->info_bits) {
- } else if (UNIV_LIKELY_NULL(block->page.zip.data)) {
+ static_assert(REC_INFO_BITS_SHIFT == 0, "compatibility");
+ if (UNIV_LIKELY_NULL(block->page.zip.data)) {
+ ut_ad(rec_offs_comp(offsets));
+ byte* info_bits = &rec[-REC_NEW_INFO_BITS];
+ const bool flip_del_mark = (*info_bits ^ update->info_bits)
+ & REC_INFO_DELETED_FLAG;
*info_bits &= ~REC_INFO_BITS_MASK;
*info_bits |= update->info_bits;
+
+ if (flip_del_mark) {
+ page_zip_rec_set_deleted(block, rec, update->info_bits
+ & REC_INFO_DELETED_FLAG, mtr);
+ }
} else {
- mtr->write<1>(*block, info_bits,
+ byte* info_bits = &rec[rec_offs_comp(offsets)
+ ? -REC_NEW_INFO_BITS
+ : -REC_OLD_INFO_BITS];
+
+ mtr->write<1,mtr_t::OPT>(*block, info_bits,
(*info_bits & ~REC_INFO_BITS_MASK)
| update->info_bits);
}