diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-02-01 18:36:03 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-02-01 18:53:41 +0200 |
commit | 44314c768f45ff7f0ad5d1133f4fd9ae0df12585 (patch) | |
tree | 4bb6f910b2636cfec3b4f6c8ee40019a1ca92a08 /mysql-test/suite/gcol | |
parent | 29240b50e3249f7905898b3332b82a1e98ff9355 (diff) | |
download | mariadb-git-44314c768f45ff7f0ad5d1133f4fd9ae0df12585.tar.gz |
MDEV-15165 InnoDB purge for index on virtual column is trying to access an incomplete record
The algorithm change is based on a MySQL 8.0 fix for
BUG #26818787: ASSERTION: DATA0DATA.IC:430:TUPLE
by Krzysztof Kapuścik
https://github.com/mysql/mysql-server/commit/ee606e62bbddd7ac3579b4a20ef8684fa7cd83fe
If a record had been inserted in place of a delete-marked purgeable
record by modifying that record, and purge was accessing that record
before the off-page columns were written, row_build_index_entry()
would have returned NULL, causing a crash.
row_vers_non_virtual_fields_equal(): Check whether all non-virtual fields
of an index are equal. Replaces row_vers_non_vc_match(). A more complex
version of this function was called row_vers_non_vc_index_entry_match()
in the MySQL 8.0 fix.
row_vers_impl_x_locked_low(): This change is not directly related to
the reported problem, but apparently to the removal of the function
row_vers_non_vc_match(). This function checks if a secondary index
record was modified by a transaction that has not been committed yet.
For comparing the non-virtual columns, construct a secondary index
tuple from the table row.
row_vers_vc_matches_cluster(): Replace row_vers_non_vc_match() with
code that is equivalent to the row_vers_non_vc_index_entry_match()
in the MySQL 8.0 fix. Also, deduplicate some code by using goto.
Diffstat (limited to 'mysql-test/suite/gcol')
-rw-r--r-- | mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result | 26 | ||||
-rw-r--r-- | mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test | 29 |
2 files changed, 53 insertions, 2 deletions
diff --git a/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result b/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result index ac4be0dcc6c..309d8e8f04a 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result @@ -145,7 +145,8 @@ connection default; update t set a = repeat('m', 16000) where a like "aaa%"; connect lock_table, localhost, root; lock table t write; -disconnect prevent_purge; +connection prevent_purge; +commit; connection default; InnoDB 0 transactions not purged disconnect lock_table; @@ -154,5 +155,28 @@ commit; InnoDB 0 transactions not purged set global debug_dbug=@old_dbug; drop table t; +# +# MDEV-15165 InnoDB purge for index on virtual column +# is trying to access an incomplete record +# +CREATE TABLE t1( +u INT PRIMARY KEY, b BLOB, ug INT GENERATED ALWAYS AS (u) VIRTUAL, +INDEX bug(b(100),ug) +) ENGINE=InnoDB; +INSERT INTO t1 (u,b) VALUES(1,REPEAT('a',16384)); +connection prevent_purge; +start transaction with consistent snapshot; +connection default; +DELETE FROM t1; +SET DEBUG_SYNC='blob_write_middle SIGNAL halfway WAIT_FOR purged'; +INSERT INTO t1 (u,b) VALUES(1,REPEAT('a',16384)); +connection prevent_purge; +SET DEBUG_SYNC='now WAIT_FOR halfway'; +COMMIT; +InnoDB 0 transactions not purged +SET DEBUG_SYNC='now SIGNAL purged'; +disconnect prevent_purge; +connection default; +DROP TABLE t1; set debug_sync=reset; SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test index 1862de268af..ad733eee3a7 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test @@ -184,7 +184,8 @@ connection default; update t set a = repeat('m', 16000) where a like "aaa%"; connect(lock_table, localhost, root); lock table t write; -disconnect prevent_purge; +connection prevent_purge; +commit; connection default; --source ../../innodb/include/wait_all_purged.inc disconnect lock_table; @@ -194,6 +195,32 @@ commit; set global debug_dbug=@old_dbug; drop table t; +--echo # +--echo # MDEV-15165 InnoDB purge for index on virtual column +--echo # is trying to access an incomplete record +--echo # +CREATE TABLE t1( + u INT PRIMARY KEY, b BLOB, ug INT GENERATED ALWAYS AS (u) VIRTUAL, + INDEX bug(b(100),ug) +) ENGINE=InnoDB; +INSERT INTO t1 (u,b) VALUES(1,REPEAT('a',16384)); +connection prevent_purge; +start transaction with consistent snapshot; +connection default; +DELETE FROM t1; +SET DEBUG_SYNC='blob_write_middle SIGNAL halfway WAIT_FOR purged'; +send INSERT INTO t1 (u,b) VALUES(1,REPEAT('a',16384)); +connection prevent_purge; +SET DEBUG_SYNC='now WAIT_FOR halfway'; +COMMIT; +--source ../../innodb/include/wait_all_purged.inc +SET DEBUG_SYNC='now SIGNAL purged'; +disconnect prevent_purge; + +connection default; +reap; +DROP TABLE t1; + --source include/wait_until_count_sessions.inc set debug_sync=reset; SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; |