| Bug #101260 | Off-by-one error in fil_system sharding | ||
|---|---|---|---|
| Submitted: | 21 Oct 2020 7:42 | Modified: | 8 Dec 2020 21:19 |
| Reporter: | Alexey Kopytov | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: InnoDB storage engine | Severity: | S3 (Non-critical) |
| Version: | 8.0 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
[21 Oct 2020 14:06]
MySQL Verification Team
Hello Kaamos, Thank you for your bug report. We have carefully analysed the code and we concluded that you are correct. Verified as reported.
[8 Dec 2020 21:19]
Daniel Price
Posted by developer: Fixed as of the upcoming 8.0.23 release, and here's the proposed changelog entry from the documentation team: An off-by-one error in Fil_system sharding code was corrected, and the maximum number of shards (MAX_SHARDS) was changed to 69.
[9 Dec 2020 13:36]
MySQL Verification Team
Thank you, Daniel .......

Description: The following code in storage/innobase/fil0fil.cc: ``` /** Maximum number of shards supported. */ static const size_t MAX_SHARDS = 64; /** The redo log is in its own shard. */ static const size_t REDO_SHARD = MAX_SHARDS - 1; /** Number of undo shards to reserve. */ static const size_t UNDO_SHARDS = 4; /** The UNDO logs have their own shards (4). */ static const size_t UNDO_SHARDS_START = REDO_SHARD - (UNDO_SHARDS + 1); ... Fil_shard *shard_by_id(space_id_t space_id) const MY_ATTRIBUTE((warn_unused_result)) { if (space_id == dict_sys_t::s_log_space_first_id) { return (m_shards[REDO_SHARD]); } else if (fsp_is_undo_tablespace(space_id)) { const size_t limit = space_id % UNDO_SHARDS; return (m_shards[UNDO_SHARDS_START + limit]); } ut_ad(m_shards.size() == MAX_SHARDS); ``` There's clearly an off-by-one error here: shard #62 will never be used, because we don't really need that "+ 1" when defining UNDO_SHARDS_START to "REDO_SHARD - (UNDO_SHARDS + 1)" While we are at it, can we define MAX_SHARDS to 69 to make division by UNDO_SHARDS_START fast? We divide by UNDO_SHARDS (which is already a power of two) and UNDO_SHARDS_START, which is currently 58 (will be 59 after the fix). We never divide by MAX_SHARDS, so if we define it to 69, calculating the shard for regular tablespaces will also become a simple bit operation. How to repeat: Look at the code snippet above.