Bug #115331 Incorrect initial_size of undo tablespace after crash recovery
Submitted: 14 Jun 9:32 Modified: 14 Jun 9:47
Reporter: Shay Fabio (OCA) Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Information schema Severity:S3 (Non-critical)
Version:8.0 OS:Any
Assigned to: CPU Architecture:Any
Tags: Contribution mysql-cluster-gpl-7.1.8ve, undo

[14 Jun 9:32] Shay Fabio
Description:
The initial_size of undo tablespace is incorrect after crash recovery.

During crash recovery, the fil_node_t of undo tablespaces is re-created and its initial size is reset to zero. Ref the following code:

```
  fil_tablespace_open_for_recovery
    ...
    ibd_open_for_recovery
      ...
      file = create_node(df.filepath(), 0, space, false, true, false); // The size is 0, it is incorrect for a undo tablespace,
```

If the undo tablespace has already been successfully created, the srv_undo_tablespace_open function will not attempt to recreate it. 
However, in srv_undo_tablespace_open function, the initial_size for an undo tablespace is determined by the current actual file size which is a more reasonable value.

Ref the following code in function srv_undo_tablespace_open:

```
fil_space_t *space = fil_space_get(space_id);
...
if (space == nullptr)
{
  space = fil_space_create(undo_name, space_id, flags, FIL_TYPE_TABLESPACE);
  ut_a(space != nullptr);
  ut_ad(fil_validate());

  os_offset_t size = os_file_get_size(fh);
  ut_a(size != (os_offset_t)-1);
  page_no_t n_pages = static_cast<page_no_t>(size / UNIV_PAGE_SIZE);

  if (fil_node_create(file_name, n_pages, space, false, atomic_write) ==
        nullptr)
  ...
}
``

How to repeat:
1. Run a sysbench script. Here is my script:

  sysbench --db-driver=mysql --mysql-host=127.0.0.1 --mysql-port=8533 --mysql-user=***** --mysql-password=**** --threads=32 --tables=1 --mysql-db=sbtest --report-interval=1  --time=300  oltp_read_write run

  This is to make MySQL go through the crash recovery phase during the 
  subsequent restart process.

2. Kill the mysqld process.

3. Restart the mysqld process.

4. Execute the sql "select file_name, initial_size from information_schema.files where tablespace_name like '%undo%';", and it will be found that the INITIAL_SIZE of the undo tablespace is 0, which is unreasonable.

Suggested fix:
It is advisable that the logic for setting the initial_size of undo tablespaces during crash recovery mirrors the behavior implemented within the srv_undo_tablespace_open function.

Code of 'correct initial_size of undo tablespaces'

(*) I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.

diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 472f87ec4da..1b796159f48 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -6220,7 +6220,14 @@ fil_load_status Fil_shard::ibd_open_for_recovery(space_id_t space_id,
 
   const fil_node_t *file;
 
-  file = create_node(df.filepath(), 0, space, false, true, false);
+  /* For undo tablespaces, the behavior aligns with the setting of initial_size
+  within the srv_undo_tablespace_open function. */
+  page_no_t n_pages = 0;
+  if (fsp_is_undo_tablespace(space->id)) {
+    n_pages = static_cast<page_no_t>(size / UNIV_PAGE_SIZE);
+  }
+
+  file = create_node(df.filepath(), n_pages, space, false, true, false);
 
   ut_a(file != nullptr);
[14 Jun 9:45] Shay Fabio
Fix incorrect initial_size of undo tablespace

(*) I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.

Contribution: Fix incorrect initial_size of undo tablespace.txt (text/plain), 758 bytes.

[14 Jun 9:47] MySQL Verification Team
Hello Shay Fabio,

Thank you for the report and contribution.

regards,
Umesh