Details
-
Bug
-
Status: Closed (View Workflow)
-
Blocker
-
Resolution: Fixed
-
10.5, 10.6, 10.11, 11.1(EOL), 10.4(EOL), 10.10(EOL), 11.0(EOL)
-
None
Description
create table t1 ( |
f1 varchar(25), |
v1 mediumtext generated always as (concat('f1:', f1)) virtual, |
unique key (f1) using hash, |
key (v1(1000)) |
);
|
insert t1 (f1) values (9599),(94410); |
check table t1 extended; |
drop table t1; |
What happens here is the following sequence of events:
- There's an update, it modifies the value of a bob virtual column
- The column is indexed, so it's recalculated
- The pointer to the value (it's a blob) is stored in the record[0]. As it's a virtual calculated column, the value is owned by the Field_blob and stored in the Field_blob::value.
- The previous value of the field (also calculated) is in Field_blob::read_value, and the pointer is in record[1].
- Now comes check_duplicate_long_entry_key(), it calculates the hash value, saves record[0] in the lookup_buffer, and performs an index_read() using a separate lookup_handler.
- In this case we have a hash collision, so a row is found, it's read into the record[0]
- Virtual columns are computed and the new value is stored in Field_blob::value, replacing the old one
- The row from the hash collision isn't identical to the one in the lookup_buffer, so check_duplicate_long_entry_key() decides it's not a duplicate key, restores record[0] from lookup_buffer and proceeds with the update
- but the blob value in Field_blob::value is lost
This isn't exactly a new kind of problems, this has happened before a few times in partitioning (MDEV-18734, 160d97a4aaac), in innodb (MDEV-15114, ab194666564a), in REPLACE and UPDATE (ea1b25046c81, that's how Field_blob::read_value was born). The fix is to detach temporarily the pointer in the record from Field_blob::value and reattach it back later.