• Marko Mäkelä's avatar
    MDEV-22924 Corruption in MVCC read via secondary index · f99cace7
    Marko Mäkelä authored
    An unsafe optimization was introduced by
    commit 2347ffd8 (MDEV-20301)
    which is based on
    mysql/mysql-server@3f3136188f1bd383f77f97823cf6ebd72d5e4d7e or
    mysql/mysql-server@647a3814a91c3d3bffc70ddff5513398e3f37bd4
    in MySQL 8.0.12 or MySQL 8.0.13
    (which in turn is based on the contribution in MySQL Bug #84958).
    
    Row_sel_get_clust_rec_for_mysql::operator(): In addition to checking
    that the pointer to the record matches, also check the latest
    modification of the page (FIL_PAGE_LSN) as well as the page identifier.
    Only if all three match, it is safe to reuse cached_old_vers.
    
    Row_sel_get_clust_rec_for_mysql::check_eq(): Assert that the PRIMARY KEY
    of the cached old version of the record corresponds to the latest version.
    
    We got a test case where CHECK TABLE, UPDATE and purge would be
    hammering on the same table (with only 6 rows) and a pointer that
    was originally pointing to a record pk=2 would match a cached_clust_rec
    that was pointing to a record pk=1. In the diagnosed `rr replay` trace,
    we would wrongly return an old cached version of the pk=1 record,
    instead of retrieving the correct version of the pk=2 record. Because
    of this, CHECK TABLE would fail to count one of the records in a
    secondary index, and report failure.
    
    This bug appears to affect MVCC reads via secondary indexes only.
    The purge of history in secondary indexes uses a different code path,
    and so do checks for implicit record locks.
    f99cace7
dict0mem.h 67.6 KB