@@ -328,9 +328,6 @@ enum fil_operation_t {
328
328
/* * The null file address */
329
329
fil_addr_t fil_addr_null = {FIL_NULL, 0 };
330
330
331
- /* * Maximum number of pages to read to determine the space ID. */
332
- static const size_t MAX_PAGES_TO_READ = 1 ;
333
-
334
331
#ifndef UNIV_HOTBACKUP
335
332
/* * Maximum number of shards supported. */
336
333
static const size_t MAX_SHARDS = 68 ;
@@ -1627,9 +1624,12 @@ class Fil_system {
1627
1624
mapping table. */
1628
1625
dberr_t scan () { return m_dirs.scan (); }
1629
1626
1630
- /* * Get the tablespace ID from an .ibd and/or an undo tablespace. If the ID is
1631
- 0 on the first page then try finding the ID with Datafile::find_space_id().
1632
- @param[in] filename File name to check
1627
+ /* * Get the tablespace ID from an .ibd and/or an undo tablespace. If the
1628
+ read failed or the ID is 0 on the first page or there is a mismatch of
1629
+ space_ids stored in FSP_SPACE_ID and FIL_PAGE_SPACE_ID, then try finding
1630
+ the ID with Datafile::find_space_id(). This function should only be called
1631
+ during server startup.
1632
+ @param[in] filename File name to check
1633
1633
@return s_invalid_space_id if not found, otherwise the space ID */
1634
1634
[[nodiscard]] static space_id_t get_tablespace_id (
1635
1635
const std::string &filename);
@@ -10954,116 +10954,62 @@ static bool fil_op_replay_rename(const page_id_t &page_id,
10954
10954
return true ;
10955
10955
}
10956
10956
10957
- /* * Get the tablespace ID from an .ibd and/or an undo tablespace. If the ID is 0
10958
- on the first page then try finding the ID with Datafile::find_space_id().
10959
- @param[in] filename File name to check
10960
- @return s_invalid_space_id if not found, otherwise the space ID */
10961
10957
space_id_t Fil_system::get_tablespace_id (const std::string &filename) {
10962
- FILE *fp = fopen (filename.c_str (), " rb" );
10963
-
10964
- if (fp == nullptr ) {
10965
- ib::warn (ER_IB_MSG_372) << " Unable to open '" << filename << " '" ;
10966
- return dict_sys_t ::s_invalid_space_id;
10967
- }
10958
+ constexpr size_t read_size = UNIV_SECTOR_SIZE;
10959
+ pfs_os_file_t file;
10960
+ bool success;
10968
10961
10969
- std::vector<space_id_t > space_ids;
10970
- auto page_size = srv_page_size;
10962
+ /* Lambda function for heavy-duty method of finding the space id from
10963
+ Datafile::find_space_id() which we fallback into, if the first page
10964
+ cannot be read properly. */
10965
+ const auto find_space_id_reliably = [&filename]() -> space_id_t {
10966
+ Datafile data_file;
10971
10967
10972
- space_ids.reserve (MAX_PAGES_TO_READ);
10968
+ data_file.set_filepath (filename.c_str ());
10969
+ const dberr_t err = data_file.open_read_only (false );
10973
10970
10974
- const auto n_bytes = page_size * MAX_PAGES_TO_READ;
10971
+ ut_a (data_file.is_open ());
10972
+ ut_a (err == DB_SUCCESS);
10975
10973
10976
- std::unique_ptr<byte[]> buf (new byte[n_bytes]);
10974
+ /* Use the heavier Datafile::find_space_id() method to find the space id. */
10975
+ return (data_file.find_space_id () == DB_SUCCESS)
10976
+ ? data_file.space_id ()
10977
+ : dict_sys_t ::s_invalid_space_id;
10978
+ };
10977
10979
10978
- if (!buf) {
10980
+ /* Open the file with O_DIRECT flag for faster access */
10981
+ file = os_file_create (innodb_data_file_key, filename.c_str (), OS_FILE_OPEN,
10982
+ OS_DATA_FILE_FOR_SPACE_ID_READ, true , &success);
10983
+ if (!success) {
10984
+ os_file_get_last_error (true );
10985
+ ib::warn (ER_IB_MSG_372) << " Unable to open '" << filename << " '" ;
10979
10986
return dict_sys_t ::s_invalid_space_id;
10980
10987
}
10981
10988
10982
- auto pages_read = fread (buf.get (), page_size, MAX_PAGES_TO_READ, fp);
10983
-
10984
- DBUG_EXECUTE_IF (" invalid_header" , pages_read = 0 ;);
10985
-
10986
- /* Find the space id from the pages read if enough pages could be read.
10987
- Fall back to the more heavier method of finding the space id from
10988
- Datafile::find_space_id() if pages cannot be read properly. */
10989
- if (pages_read >= MAX_PAGES_TO_READ) {
10990
- auto bytes_read = pages_read * page_size;
10991
-
10992
- #ifdef POSIX_FADV_DONTNEED
10993
- posix_fadvise (fileno (fp), 0 , bytes_read, POSIX_FADV_DONTNEED);
10994
- #endif /* POSIX_FADV_DONTNEED */
10995
-
10996
- for (page_no_t i = 0 ; i < MAX_PAGES_TO_READ; ++i) {
10997
- const auto off = i * page_size + FIL_PAGE_SPACE_ID;
10998
-
10999
- if (off == FIL_PAGE_SPACE_ID) {
11000
- /* Find out the page size of the tablespace from the first page.
11001
- In case of compressed pages, the subsequent pages can be of different
11002
- sizes. If MAX_PAGES_TO_READ is changed to a different value, then the
11003
- page size of subsequent pages is needed to find out the offset for
11004
- space ID. */
11005
-
11006
- auto space_flags_offset = FSP_HEADER_OFFSET + FSP_SPACE_FLAGS;
11007
-
11008
- ut_a (space_flags_offset + 4 < n_bytes);
11009
-
11010
- const auto flags = mach_read_from_4 (buf.get () + space_flags_offset);
11011
-
11012
- page_size_t space_page_size (flags);
11013
-
11014
- page_size = space_page_size.physical ();
11015
- }
11016
-
11017
- space_ids.push_back (mach_read_from_4 (buf.get () + off));
10989
+ space_id_t space_id = dict_sys_t ::s_invalid_space_id;
11018
10990
11019
- if ((i + 1 ) * page_size >= bytes_read) {
11020
- break ;
11021
- }
11022
- }
11023
- }
10991
+ auto buf = ut::make_unique_aligned<byte[]>(read_size, read_size);
11024
10992
11025
- fclose (fp);
10993
+ IORequest request (IORequest::READ);
10994
+ ulint bytes_read = 0 ;
11026
10995
11027
- space_id_t space_id;
10996
+ dberr_t err = os_file_read_no_error_handling (
10997
+ request, filename.c_str (), file, buf.get (), 0 , read_size, &bytes_read);
11028
10998
11029
- if (!space_ids.empty ()) {
11030
- space_id = space_ids.front ();
10999
+ os_file_close (file);
11031
11000
11032
- for (auto id : space_ids) {
11033
- if (id == 0 || space_id != id) {
11034
- space_id = UINT32_UNDEFINED;
11001
+ DBUG_EXECUTE_IF (" invalid_header" , bytes_read = 0 ;);
11035
11002
11036
- break ;
11037
- }
11038
- }
11039
- } else {
11040
- space_id = UINT32_UNDEFINED;
11003
+ if (err != DB_SUCCESS || (bytes_read != read_size)) {
11004
+ /* Reading from the first page failed, falling back to heavy duty method */
11005
+ return find_space_id_reliably ();
11041
11006
}
11042
11007
11043
- /* Try the more heavy duty method, as a last resort. */
11044
- if (space_id == UINT32_UNDEFINED) {
11045
- /* If the first page cannot be read properly, then for compressed
11046
- tablespaces we don't know where the page boundary starts because
11047
- we don't know the page size. */
11048
-
11049
- Datafile file;
11050
-
11051
- file.set_filepath (filename.c_str ());
11052
-
11053
- dberr_t err = file.open_read_only (false );
11054
-
11055
- ut_a (file.is_open ());
11056
- ut_a (err == DB_SUCCESS);
11057
-
11058
- /* Use the heavier Datafile::find_space_id() method to
11059
- find the space id. */
11060
- err = file.find_space_id ();
11061
-
11062
- if (err == DB_SUCCESS) {
11063
- space_id = file.space_id ();
11064
- }
11008
+ /* Read the space_id from buf at offset FIL_PAGE_SPACE_ID */
11009
+ space_id = fsp_header_get_space_id (buf.get ());
11065
11010
11066
- file.close ();
11011
+ if (space_id == 0 || space_id == SPACE_UNKNOWN) {
11012
+ return find_space_id_reliably ();
11067
11013
}
11068
11014
11069
11015
return space_id;
0 commit comments