Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Fixed
-
10.11
-
None
-
Unexpected results
-
Q4/2026 Server Maintenance
Description
Reproduce
--source include/have_innodb.inc
|
 |
create table t1 (id int primary key, a text charset latin1, |
s text charset utf8mb4 as (concat('s-', a)) stored, key (s(10))) |
with system versioning engine=innodb; |
insert t1 (id, a) values (1, 'old'), (2, 'old-and-longer'); |
--echo # UPDATE (vers_insert_history_row)
|
update t1 set a= 'new'; |
--echo # REPLACE (delete_row<true>)
|
replace t1 (id, a) values (2, 'final'); |
check table t1 extended; |
select id, a, s, s = concat('s-', a) as ok from t1 for system_time all |
order by id, a; |
drop table t1; |
Result
check table t1 extended; |
Table Op Msg_type Msg_text |
test.t1 check status OK |
select id, a, s, s = concat('s-', a) as ok from t1 for system_time all |
order by id, a; |
id a s ok
|
1 new s-new 1
|
1 old s-old 1
|
2 final s-newal 0
|
2 new s-new 1
|
2 old-and-longer s-old-and-longer 1 |
Expected
id a s ok
|
1 new s-new 1
|
1 old s-old 1
|
2 final s-final 1
|
2 new s-new 1
|
2 old-and-longer s-old-and-longer 1 |
The current row written by REPLACE must have s = 's-final'. It gets the first bytes of the history row's value 's-new' written over 's-final'. CHECK TABLE does not detect it, because the index on s holds the same wrong value.
Notes
REPLACE into a system-versioned table turns the conflicting row into history in TABLE::delete_row<true>(): it saves the new row into record[2], restores the conflicting row from record[1] and calls vers_update_end(). Its VCOL_UPDATE_FOR_WRITE computation recomputes the stored generated column of the history row into Field_blob::value, the buffer that s of the new row in record[2] points to. Field_blob::store() copies into value here because of the character set conversion (latin1 to utf8mb4).
The same mechanism was fixed for virtual (non-stored) blob columns in MDEV-39306 and MDEV-41493: remember_blob_values() saves Field_blob::value around vers_update_end(). The guard covers only non-stored columns (virtual_not_stored_blob_fields), so stored generated blob columns stay affected.
The UPDATE in the test case writes the history row with vers_insert_history_row(), which has the same sequence, but its result is correct here.
Attachments
Issue Links
- relates to
-
MDEV-39306 Index corruption on UPDATE when using versioned InnoDB table (on UPDATE)
-
- Closed
-