From 3b10e8f80c434277207db9a613d9110c8283ea6a Mon Sep 17 00:00:00 2001 From: Vlad Lesin Date: Wed, 9 Feb 2022 16:50:28 +0300 Subject: [PATCH 1/4] MDEV-27746 Wrong comparision of BLOB's empty preffix with non-preffixed BLOB causes rows count mismatch for clustered and secondary indexes during non-locking read row_sel_sec_rec_is_for_clust_rec() treats empty BLOB prefix field in secondary index as a field equal to any external BLOB field in clustered index. Row_sel_get_clust_rec_for_mysql::operator() doesn't zerro out clustered record pointer in row_search_mvcc(), and row_search_mvcc() thinks that delete-marked secondary index record has visible for "CHECK TABLE"'s read view old-versioned clustered index record, and row_scan_index_for_mysql() counts it as a row. The fix is to execute row_sel_sec_rec_is_for_blob() in row_sel_sec_rec_is_for_clust_rec() if clustered field contains BLOB's reference. --- .../suite/innodb/r/blob_cmp_empty.result | 19 ++++++++++++++ mysql-test/suite/innodb/t/blob_cmp_empty.test | 26 +++++++++++++++++++ storage/innobase/row/row0sel.cc | 8 +++++- 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/innodb/r/blob_cmp_empty.result create mode 100644 mysql-test/suite/innodb/t/blob_cmp_empty.test diff --git a/mysql-test/suite/innodb/r/blob_cmp_empty.result b/mysql-test/suite/innodb/r/blob_cmp_empty.result new file mode 100644 index 00000000000..24ae8e1c01e --- /dev/null +++ b/mysql-test/suite/innodb/r/blob_cmp_empty.result @@ -0,0 +1,19 @@ +connect prevent_purge,localhost,root,,; +start transaction with consistent snapshot; +connection default; +SET @fill_amount = (@@innodb_page_size / 2 ) + 1; +CREATE TABLE t1 (col_text TEXT NOT NULL, KEY (col_text(9))) ENGINE=InnoDB; +INSERT INTO t1 (col_text) VALUES (REPEAT('x', @fill_amount)); +UPDATE t1 SET col_text=''; +UPDATE t1 SET col_text=REPEAT('y', @fill_amount); +connect con1,localhost,root,,; +SET @fill_amount = (@@innodb_page_size / 2 ) + 1; +BEGIN; +INSERT INTO t1 (col_text) VALUES (REPEAT('z', @fill_amount)); +connection default; +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +disconnect con1; +disconnect prevent_purge; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/blob_cmp_empty.test b/mysql-test/suite/innodb/t/blob_cmp_empty.test new file mode 100644 index 00000000000..f41ac79b16f --- /dev/null +++ b/mysql-test/suite/innodb/t/blob_cmp_empty.test @@ -0,0 +1,26 @@ +--source include/innodb_row_format.inc +--source include/count_sessions.inc +--connect(prevent_purge,localhost,root,,) +start transaction with consistent snapshot; + +--connection default +SET @fill_amount = (@@innodb_page_size / 2 ) + 1; +CREATE TABLE t1 (col_text TEXT NOT NULL, KEY (col_text(9))) ENGINE=InnoDB; + +INSERT INTO t1 (col_text) VALUES (REPEAT('x', @fill_amount)); +UPDATE t1 SET col_text=''; +UPDATE t1 SET col_text=REPEAT('y', @fill_amount); + +--connect(con1,localhost,root,,) +SET @fill_amount = (@@innodb_page_size / 2 ) + 1; +BEGIN; +INSERT INTO t1 (col_text) VALUES (REPEAT('z', @fill_amount)); + +--connection default +# If the bug is not fixed, CHECK TABLE will complain about wrong secondary index +# rows count +CHECK TABLE t1; +--disconnect con1 +--disconnect prevent_purge +DROP TABLE t1; +--source include/wait_until_count_sessions.inc diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 87c67edff4b..d513ab09dcf 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -352,11 +352,16 @@ row_sel_sec_rec_is_for_clust_rec( } len = clust_len; + ulint prefix_len = ifield->prefix_len; if (rec_offs_nth_extern(clust_offs, clust_pos)) { + /* BLOB can contain prefix. */ len -= BTR_EXTERN_FIELD_REF_SIZE; + if (!len) { + goto compare_blobs; + } } - if (ulint prefix_len = ifield->prefix_len) { + if (prefix_len) { len = dtype_get_at_most_n_mbchars( col->prtype, col->mbminlen, col->mbmaxlen, prefix_len, len, @@ -369,6 +374,7 @@ row_sel_sec_rec_is_for_clust_rec( check_for_blob: if (rec_offs_nth_extern(clust_offs, clust_pos)) { +compare_blobs: if (!row_sel_sec_rec_is_for_blob( col->mtype, col->prtype, col->mbminlen, From 1a7573d5a5f79fd46b6905433b18c812d74c46cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 11 Feb 2022 12:58:42 +0200 Subject: [PATCH 2/4] Disable innodb_gis.rtree_compress2 --- mysql-test/suite/innodb_gis/disabled.def | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/innodb_gis/disabled.def b/mysql-test/suite/innodb_gis/disabled.def index bf500c1cb93..2d4d3686dd1 100644 --- a/mysql-test/suite/innodb_gis/disabled.def +++ b/mysql-test/suite/innodb_gis/disabled.def @@ -12,3 +12,4 @@ rtree_concurrent_srch : MDEV-15284 COUNT(*) mismatch rtree_recovery : MDEV-15284 COUNT(*) mismatch +rtree_compress2 : MDEV-16269 CHECK TABLE reports wrong count From e50421be21e86541fa3815c09525623f33b3818d Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Sat, 12 Feb 2022 15:18:56 -0500 Subject: [PATCH 3/4] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 6deead00756..bffeddf780b 100644 --- a/VERSION +++ b/VERSION @@ -1,4 +1,4 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=3 -MYSQL_VERSION_PATCH=34 +MYSQL_VERSION_PATCH=35 SERVER_MATURITY=stable From e777645d483420fb65e26bb20fde4f0f9ebcd05c Mon Sep 17 00:00:00 2001 From: Daniel Bartholomew Date: Sat, 12 Feb 2022 15:43:53 -0500 Subject: [PATCH 4/4] bump the VERSION --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index d9c4622d96b..1686f2ed10d 100644 --- a/VERSION +++ b/VERSION @@ -1,3 +1,3 @@ MYSQL_VERSION_MAJOR=10 MYSQL_VERSION_MINOR=2 -MYSQL_VERSION_PATCH=43 +MYSQL_VERSION_PATCH=44