1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

Merge 10.6 into 10.11

This commit is contained in:
Marko Mäkelä
2025-11-11 10:29:45 +02:00
20 changed files with 285 additions and 243 deletions

View File

@@ -6096,16 +6096,12 @@ exit:
ut_ad(fil_space_t::physical_size(flags) == info.page_size);
mysql_mutex_lock(&fil_system.mutex);
fil_space_t* space = fil_space_t::create(uint32_t(info.space_id),
flags, false, 0,
FIL_ENCRYPTION_DEFAULT, true);
std::ignore = fil_space_t::create(uint32_t(info.space_id),
flags, false, 0,
FIL_ENCRYPTION_DEFAULT, true);
mysql_mutex_unlock(&fil_system.mutex);
if (space) {
*success = xb_space_create_file(real_name, info.space_id,
flags, &file);
} else {
msg("Can't create tablespace %s\n", dest_space_name);
}
*success = xb_space_create_file(real_name, info.space_id,
flags, &file);
goto exit;
}

View File

@@ -189,6 +189,9 @@ public:
ListNode *prev= pos.node_->prev;
ListNode *next= pos.node_->next;
DBUG_ASSERT(prev->next == pos.node_);
DBUG_ASSERT(next->prev == pos.node_);
prev->next= next;
next->prev= prev;
@@ -202,7 +205,7 @@ public:
}
void push_back(reference value) noexcept { insert(end(), value); }
void pop_back() noexcept { erase(end()); }
void pop_back() noexcept { erase(--end()); }
void push_front(reference value) noexcept { insert(begin(), value); }
void pop_front() noexcept { erase(begin()); }

View File

@@ -220,4 +220,26 @@ SELECT * FROM t1;
a b
1 1
2 1
connect ddl, localhost, root;
SET DEBUG_SYNC = 'fil_ibd_create_logged SIGNAL stuck WAIT_FOR ever';
ALTER TABLE t1 FORCE;
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR stuck';
# Kill the server
disconnect ddl;
# restart
CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` int(11) DEFAULT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
SELECT * FROM t1;
a b
1 1
2 1
DROP TABLE t1;

View File

@@ -36,6 +36,10 @@ BEGIN;
INSERT INTO t1 VALUES(42);
connect con1,localhost,root;
CREATE TABLE bug16735660 (a INT PRIMARY KEY) ENGINE=InnoDB;
SET GLOBAL innodb_max_purge_lag_wait=2;
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0;
SET GLOBAL innodb_max_dirty_pages_pct=0.0;
SET GLOBAL innodb_max_dirty_pages_pct=90.0;
XA START 'x';
INSERT INTO bug16735660 VALUES(1),(2),(3);
XA END 'x';

View File

@@ -1920,16 +1920,10 @@ CREATE TABLE t2(f1 INT PRIMARY KEY)ENGINE=InnoDB;
# Kill the server
# Wrong space_id in a dirty file and a missing file
# restart
SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
# Restore t1 and t2
# restart
SELECT * FROM t1;
f1
SELECT * FROM t2;
f1
CHECK TABLE t1, t2;
Table Op Msg_type Msg_text
test.t1 check status OK
test.t2 check status OK
DROP TABLE t1, t2;
#
# MDEV-18186 assertion failure on missing InnoDB index

View File

@@ -19,23 +19,6 @@ WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
FOUND 1 /InnoDB: Ignoring data file '.*t2.ibd' with space ID \d+. Another data file called .*t1.ibd exists with the same space ID/ in mysqld.1.err
# Fault 2: Wrong space_id in a dirty file, and a missing file.
# restart
SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
FOUND 1 /InnoDB: Tablespace \d+ was not found at.*t3.ibd/ in mysqld.1.err
# Fault 3: Wrong space_id in a dirty file, and no missing file.
# restart
SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
FOUND 1 /InnoDB: Ignoring data file '.*t[23].ibd' with space ID/ in mysqld.1.err
NOT FOUND /InnoDB: Tablespace \d+ was not found at .*t1.ibd/ in mysqld.1.err
FOUND 1 /InnoDB: Tablespace \d+ was not found at .*t3.ibd/ in mysqld.1.err
FOUND 2 /InnoDB: Set innodb_force_recovery=1 to ignore this and to permanently lose all changes to the tablespace/ in mysqld.1.err
# Fault 4: Missing data file
# restart
SELECT * FROM INFORMATION_SCHEMA.ENGINES
@@ -57,6 +40,7 @@ AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
NOT FOUND /\[Note\] InnoDB: Cannot read first page of .*t2.ibd/ in mysqld.1.err
FOUND 1 /.*\[ERROR\] InnoDB: Cannot apply log to \[page id: space=[1-9][0-9]*, page number=3\] of corrupted file './test/t2\.ibd'/ in mysqld.1.err
# Fault 2: Wrong space_id in a dirty file, and a missing file.
# restart
SELECT * FROM t2;
a
@@ -78,6 +62,16 @@ CREATE TABLE t0(a INT PRIMARY KEY) ENGINE=InnoDB;
ERROR HY000: Can't create table `test`.`t0` (errno: 184 "Tablespace already exists")
CREATE TABLE t0(a INT PRIMARY KEY) ENGINE=InnoDB;
DROP TABLE t0;
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
ERROR HY000: Can't create table `test`.`t1` (errno: 184 "Tablespace already exists")
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
ERROR HY000: Can't create table `test`.`t1` (errno: 184 "Tablespace already exists")
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
DROP TABLE t1;
SET GLOBAL innodb_max_purge_lag_wait=0;
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0;
SET GLOBAL innodb_max_dirty_pages_pct=0.0;
SET GLOBAL innodb_max_dirty_pages_pct=90.0;
CREATE TABLE u1(a INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE u2(a INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE u3(a INT PRIMARY KEY) ENGINE=InnoDB;

View File

@@ -223,6 +223,20 @@ SET GLOBAL innodb_fil_make_page_dirty_debug=0;
disconnect ddl;
--source include/start_mysqld.inc
CHECK TABLE t1;
SHOW CREATE TABLE t1;
SELECT * FROM t1;
connect ddl, localhost, root;
SET DEBUG_SYNC = 'fil_ibd_create_logged SIGNAL stuck WAIT_FOR ever';
send ALTER TABLE t1 FORCE;
connection default;
SET DEBUG_SYNC = 'now WAIT_FOR stuck';
--source include/kill_mysqld.inc
disconnect ddl;
--source include/start_mysqld.inc
CHECK TABLE t1;
SHOW CREATE TABLE t1;
SELECT * FROM t1;

View File

@@ -139,6 +139,17 @@ INSERT INTO t1 VALUES(42);
CREATE TABLE bug16735660 (a INT PRIMARY KEY) ENGINE=InnoDB;
# Force a log checkpoint to "discard" any FILE_CREATE records.
SET GLOBAL innodb_max_purge_lag_wait=2;
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0;
SET GLOBAL innodb_max_dirty_pages_pct=0.0;
let $wait_condition =
SELECT variable_value = 0
FROM information_schema.global_status
WHERE variable_name = 'INNODB_BUFFER_POOL_PAGES_DIRTY';
--source include/wait_condition.inc
SET GLOBAL innodb_max_dirty_pages_pct=90.0;
XA START 'x';
--source ../include/no_checkpoint_start.inc
INSERT INTO bug16735660 VALUES(1),(2),(3);

View File

@@ -1132,29 +1132,13 @@ CREATE TABLE t2(f1 INT PRIMARY KEY)ENGINE=InnoDB;
--let CLEANUP_IF_CHECKPOINT=DROP TABLE t1, t2;
--source include/no_checkpoint_end.inc
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err;
let $check_no_innodb=SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
--echo # Wrong space_id in a dirty file and a missing file
--copy_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t0.ibd
--move_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t1.ibd
--source include/start_mysqld.inc
--eval $check_no_innodb
--source include/shutdown_mysqld.inc
--echo # Restore t1 and t2
--move_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t2.ibd
--move_file $MYSQLD_DATADIR/test/t0.ibd $MYSQLD_DATADIR/test/t1.ibd
--source include/start_mysqld.inc
SELECT * FROM t1;
SELECT * FROM t2;
# Because the tables were created after the checkpoint,
# InnoDB will start up, but the tables will be corrupted.
CHECK TABLE t1, t2;
DROP TABLE t1, t2;

View File

@@ -45,53 +45,13 @@ AND support IN ('YES', 'DEFAULT', 'ENABLED');
eval $check_no_innodb;
let SEARCH_PATTERN= InnoDB: Ignoring data file '.*t2.ibd' with space ID \d+. Another data file called .*t1.ibd exists with the same space ID;
--source include/search_pattern_in_file.inc
--source include/shutdown_mysqld.inc
--remove_file $MYSQLD_DATADIR/test/t1.ibd
# This could fail to refuse InnoDB startup, in case there was a log
# checkpoint after the CREATE TABLE t3. That is what we checked above.
--echo # Fault 2: Wrong space_id in a dirty file, and a missing file.
--move_file $MYSQLD_DATADIR/test/t3.ibd $MYSQLD_DATADIR/test/t1.ibd
--source include/start_mysqld.inc
eval $check_no_innodb;
let SEARCH_PATTERN= InnoDB: Tablespace \d+ was not found at.*t3.ibd;
--source include/search_pattern_in_file.inc
--source include/shutdown_mysqld.inc
--move_file $MYSQLD_DATADIR/test/t1.ibd $MYSQLD_DATADIR/test/t3.ibd
--echo # Fault 3: Wrong space_id in a dirty file, and no missing file.
# Swap t2.ibd and t3.ibd.
--move_file $MYSQLD_DATADIR/test/t3.ibd $MYSQLD_DATADIR/test/t.ibd
--move_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t3.ibd
--move_file $MYSQLD_DATADIR/test/t.ibd $MYSQLD_DATADIR/test/t2.ibd
--source include/start_mysqld.inc
eval $check_no_innodb;
let SEARCH_PATTERN= InnoDB: Ignoring data file '.*t[23].ibd' with space ID;
--source include/search_pattern_in_file.inc
let SEARCH_PATTERN= InnoDB: Tablespace \d+ was not found at .*t1.ibd;
--source include/search_pattern_in_file.inc
let SEARCH_PATTERN= InnoDB: Tablespace \d+ was not found at .*t3.ibd;
--source include/search_pattern_in_file.inc
let SEARCH_PATTERN= InnoDB: Set innodb_force_recovery=1 to ignore this and to permanently lose all changes to the tablespace;
--source include/search_pattern_in_file.inc
--source include/shutdown_mysqld.inc
# Swap back t3.ibd, but hide t2.ibd (which the redo log also knows as t1.ibd).
--move_file $MYSQLD_DATADIR/test/t3.ibd $MYSQLD_DATADIR/test/t.ibd
--move_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t3.ibd
--echo # Fault 4: Missing data file
--move_file $MYSQLD_DATADIR/test/t2.ibd $MYSQLD_DATADIR/test/t.ibd
--remove_file $MYSQLD_DATADIR/test/t1.ibd
--source include/start_mysqld.inc
eval $check_no_innodb;
--source include/shutdown_mysqld.inc
@@ -108,15 +68,6 @@ let SEARCH_PATTERN= InnoDB: Tablespace \d+ was not found at .*t[12].ibd.
eval $check_no_innodb;
--source include/shutdown_mysqld.inc
# On Linux, lseek() would typically report EINVAL when invoked on a directory.
# On other plaftorms as well as some GNU/Linux based environments, such as
# a Ubuntu 22.04 based image on Amazon Web Services,
# os_file_get_size() would succeed on a directory, and we would get another
# error about inability to apply log to a corrupted page.
#--let SEARCH_PATTERN= InnoDB: Could not measure the size of single-table tablespace file '.*test/t2\\.ibd'
#--source include/search_pattern_in_file.inc
--rmdir $MYSQLD_DATADIR/test/t2.ibd
# Create a short file.
@@ -136,6 +87,9 @@ let SEARCH_PATTERN= .*\[ERROR\] InnoDB: Cannot apply log to \\[page id: space=[1
--remove_file $MYSQLD_DATADIR/test/t2.ibd
--move_file $MYSQLD_DATADIR/test/t.ibd $MYSQLD_DATADIR/test/t2.ibd
--echo # Fault 2: Wrong space_id in a dirty file, and a missing file.
--move_file $MYSQLD_DATADIR/test/t3.ibd $MYSQLD_DATADIR/test/t1.ibd
--source include/start_mysqld.inc
SELECT * FROM t2;
@@ -150,13 +104,20 @@ CREATE TABLE t0(a INT PRIMARY KEY) ENGINE=InnoDB;
--remove_file $MYSQLD_DATADIR/test/t0.ibd
CREATE TABLE t0(a INT PRIMARY KEY) ENGINE=InnoDB;
DROP TABLE t0;
--error ER_CANT_CREATE_TABLE
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
--error ER_CANT_CREATE_TABLE
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
--remove_file $MYSQLD_DATADIR/test/t1.ibd
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB;
DROP TABLE t1;
--disable_query_log
# The following are for the orphan file t0.ibd or for the directory t2.ibd:
call mtr.add_suppression("InnoDB: Operating system error number [0-9]* in a file operation");
call mtr.add_suppression("InnoDB: Error number \\d+ means");
call mtr.add_suppression("InnoDB: Cannot create file '.*t0.ibd'");
call mtr.add_suppression("InnoDB: The file '.*t0\.ibd' already exists");
call mtr.add_suppression("InnoDB: The file '.*t[01]\.ibd' already exists");
call mtr.add_suppression("InnoDB: Cannot open datafile for read-write: '.*t2\.ibd'");
call mtr.add_suppression("InnoDB: Could not measure the size of single-table tablespace file '.*test/t2\\.ibd'");
# The following are for aborted startup without --innodb-force-recovery:
@@ -186,6 +147,17 @@ call mtr.add_suppression("InnoDB: Cannot read first page in datafile:");
FLUSH TABLES;
--enable_query_log
# Force a log checkpoint to "discard" any FILE_CREATE records.
SET GLOBAL innodb_max_purge_lag_wait=0;
SET GLOBAL innodb_max_dirty_pages_pct_lwm=0.0;
SET GLOBAL innodb_max_dirty_pages_pct=0.0;
let $wait_condition =
SELECT variable_value = 0
FROM information_schema.global_status
WHERE variable_name = 'INNODB_BUFFER_POOL_PAGES_DIRTY';
--source include/wait_condition.inc
SET GLOBAL innodb_max_dirty_pages_pct=90.0;
--source include/no_checkpoint_start.inc
CREATE TABLE u1(a INT PRIMARY KEY) ENGINE=InnoDB;

View File

@@ -272,6 +272,7 @@ call mtr.add_suppression("InnoDB: Operating system error number .* in a file ope
call mtr.add_suppression("InnoDB: Error number .* means");
call mtr.add_suppression("InnoDB: Cannot create file");
call mtr.add_suppression("InnoDB: Failed to create");
call mtr.add_suppression("InnoDB: The file '.*test/FTS_[0-9a-f]*_BEING_DELETED\\.ibd' already exists");
CREATE TABLE t1(a TEXT, FTS_DOC_ID BIGINT UNSIGNED NOT NULL UNIQUE) ENGINE=InnoDB;
ALTER TABLE t1 ADD FULLTEXT(a), ALGORITHM=INPLACE;
ERROR HY000: Got error 11 "Resource temporarily unavailable" from storage engine InnoDB

View File

@@ -365,6 +365,7 @@ call mtr.add_suppression("InnoDB: Operating system error number .* in a file ope
call mtr.add_suppression("InnoDB: Error number .* means");
call mtr.add_suppression("InnoDB: Cannot create file");
call mtr.add_suppression("InnoDB: Failed to create");
call mtr.add_suppression("InnoDB: The file '.*test/FTS_[0-9a-f]*_BEING_DELETED\\.ibd' already exists");
let MYSQLD_DATADIR=`select @@datadir`;
CREATE TABLE t1(a TEXT, FTS_DOC_ID BIGINT UNSIGNED NOT NULL UNIQUE) ENGINE=InnoDB;

View File

@@ -2395,7 +2395,7 @@ create or replace table t1 (x int) with system versioning engine innodb
partition by system_time interval 1 hour auto;
insert into t1 values (1);
call mtr.add_suppression("rror number .*(File exists|file operation)");
call mtr.add_suppression("InnoDB: Cannot create file");
call mtr.add_suppression("InnoDB: The file '.*test/t1#P#p1\\.ibd' already exists");
set timestamp= unix_timestamp('2000-01-01 01:00:00');
update t1 set x= x + 2;
ERROR HY000: Got error 184 "Tablespace already exists" from storage engine InnoDB

View File

@@ -1904,7 +1904,7 @@ partition by system_time interval 1 hour auto;
insert into t1 values (1);
call mtr.add_suppression("rror number .*(File exists|file operation)");
call mtr.add_suppression("InnoDB: Cannot create file");
call mtr.add_suppression("InnoDB: The file '.*test/t1#P#p1\\.ibd' already exists");
--let $datadir= `select @@datadir`
--let $dummy= $datadir/test/t1#P#p1.ibd

View File

@@ -354,12 +354,16 @@ static bool fil_node_open_file_low(fil_node_t *node, const byte *page,
bool success;
node->handle= os_file_create(innodb_data_file_key, node->name,
node->is_raw_disk
? OS_FILE_OPEN_RAW : OS_FILE_OPEN,
? OS_FILE_OPEN_RAW
: node->deferred
? OS_FILE_OPEN_SILENT : OS_FILE_OPEN,
type,
srv_read_only_mode, &success);
ut_ad(success == node->is_open());
if (success && node->is_open())
{
created:
#ifndef _WIN32
if (!node->space->id && !srv_read_only_mode && my_disable_locking &&
os_file_lock(node->handle, node->name))
@@ -371,6 +375,15 @@ static bool fil_node_open_file_low(fil_node_t *node, const byte *page,
#endif
break;
}
else if (node->deferred)
{
node->handle= os_file_create(innodb_data_file_key, node->name,
OS_FILE_CREATE, type,
srv_read_only_mode, &success);
ut_ad(success == node->is_open());
if (node->is_open())
goto created;
}
/* The following call prints an error message */
if (os_file_get_last_error(true) == EMFILE + 100 &&
@@ -860,13 +873,7 @@ static void fil_space_free_low(fil_space_t *space) noexcept
/* The tablespace must not be in fil_system.named_spaces. */
ut_ad(srv_fast_shutdown == 2 || !srv_was_started
|| space->max_lsn == 0);
/* Wait for fil_space_t::release() after
fil_system_t::detach(), the tablespace cannot be found, so
fil_space_t::get() would return NULL */
while (space->referenced()) {
std::this_thread::sleep_for(std::chrono::microseconds(100));
}
ut_ad(!space->referenced());
for (fil_node_t* node = UT_LIST_GET_FIRST(space->chain);
node != NULL; ) {
@@ -921,7 +928,7 @@ bool fil_space_free(uint32_t id, bool x_latched) noexcept
} else {
ut_ad(log_sys.latch_have_wr());
if (space->max_lsn) {
ut_d(space->max_lsn = 0);
space->max_lsn = 0;
fil_system.named_spaces.remove(*space);
}
}
@@ -952,8 +959,6 @@ fil_space_t *fil_space_t::create(uint32_t id, uint32_t flags,
ut_ad(fil_space_t::is_valid_flags(flags & ~FSP_FLAGS_MEM_MASK, id));
ut_ad(srv_page_size == UNIV_PAGE_SIZE_ORIG || flags != 0);
DBUG_EXECUTE_IF("fil_space_create_failure", return nullptr;);
fil_space_t** after= fil_system.spaces.cell_get(id)->search
(&fil_space_t::hash, [id](const fil_space_t *space)
{ return !space || space->id == id; });
@@ -1587,10 +1592,24 @@ fil_space_t *fil_space_t::drop(uint32_t id, pfs_os_file_t *detached_handle)
pfs_os_file_t handle= fil_system.detach(space, true);
mysql_mutex_unlock(&fil_system.mutex);
/* The above mtr.commit_file(*space, nullptr) should remove the space from
fil_system.named_spaces. Before we set the STOPPING_WRITES flag, another
concurrent operation could have marked the tablespace dirty again.
This clean-up corresponds to fil_space_free(). */
log_sys.latch.wr_lock(SRW_LOCK_CALL);
ut_ad((space->pending() & ~NEEDS_FSYNC) == (STOPPING | CLOSING));
if (space->max_lsn != 0)
{
space->max_lsn= 0;
fil_system.named_spaces.remove(*space);
}
log_sys.latch.wr_unlock();
if (detached_handle)
*detached_handle = handle;
else
os_file_close(handle);
return space;
}
@@ -1616,12 +1635,6 @@ void fil_close_tablespace(uint32_t id) noexcept
while (buf_flush_list_space(space));
space->x_unlock();
log_sys.latch.wr_lock(SRW_LOCK_CALL);
if (space->max_lsn != 0) {
ut_d(space->max_lsn = 0);
fil_system.named_spaces.remove(*space);
}
log_sys.latch.wr_unlock();
fil_space_free_low(space);
}
@@ -1843,16 +1856,12 @@ fil_ibd_create(
uint32_t key_id,
dberr_t* err) noexcept
{
pfs_os_file_t file;
bool success;
mtr_t mtr;
bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags) != 0;
ut_ad(!is_system_tablespace(space_id));
ut_ad(!srv_read_only_mode);
ut_a(space_id < SRV_SPACE_ID_UPPER_BOUND);
ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
ut_a(fil_space_t::is_valid_flags(flags & ~FSP_FLAGS_MEM_MASK, space_id));
ut_a(fil_space_t::is_valid_flags(flags & ~FSP_FLAGS_MEM_MASK,
space_id));
/* Create the subdirectories in the path, if they are
not there already. */
@@ -1861,14 +1870,6 @@ fil_ibd_create(
return NULL;
}
mtr.start();
mtr.log_file_op(FILE_CREATE, space_id, path);
log_sys.latch.wr_lock(SRW_LOCK_CALL);
auto lsn= mtr.commit_files();
log_sys.latch.wr_unlock();
mtr.flag_wr_unlock();
log_write_up_to(lsn, true);
static_assert(((UNIV_ZIP_SIZE_MIN >> 1) << 3) == 4096,
"compatibility");
#if defined _WIN32 || defined O_DIRECT
@@ -1884,45 +1885,7 @@ fil_ibd_create(
#else
constexpr auto type = OS_DATA_FILE;
#endif
file = os_file_create(
innodb_data_file_key, path,
OS_FILE_CREATE,
type, srv_read_only_mode, &success);
if (!success) {
/* The following call will print an error message */
switch (os_file_get_last_error(true)) {
case OS_FILE_ALREADY_EXISTS:
ib::info() << "The file '" << path << "'"
" already exists though the"
" corresponding table did not exist"
" in the InnoDB data dictionary."
" You can resolve the problem by removing"
" the file.";
*err = DB_TABLESPACE_EXISTS;
break;
case OS_FILE_DISK_FULL:
*err = DB_OUT_OF_FILE_SPACE;
break;
default:
*err = DB_ERROR;
}
ib::error() << "Cannot create file '" << path << "'";
return NULL;
}
const bool is_compressed = fil_space_t::is_compressed(flags);
#ifdef _WIN32
const bool is_sparse = is_compressed;
if (is_compressed) {
os_file_set_sparse_win32(file);
}
#else
const bool is_sparse = is_compressed
&& DB_SUCCESS == os_file_punch_hole(file, 0, 4096)
&& !my_test_if_thinly_provisioned(file);
#endif
if (fil_space_t::full_crc32(flags)) {
flags |= FSP_FLAGS_FCRC32_PAGE_SSIZE();
@@ -1937,54 +1900,122 @@ fil_ibd_create(
? fil_space_create_crypt_data(mode, key_id)
: nullptr;
mysql_mutex_lock(&fil_system.mutex);
fil_space_t* space = fil_space_t::create(space_id, flags, false,
crypt_data, mode, true);
fil_node_t* node = space->add(path, OS_FILE_CLOSED, size, false, true);
space->set_stopped();
mysql_mutex_unlock(&fil_system.mutex);
buf_block_t *header[2];
{
mtr_t mtr;
mtr.start();
mtr.log_file_op(FILE_CREATE, space_id, path);
mtr.set_named_space(space);
log_free_check();
ut_a(fsp_header_init(space, size, &mtr) == DB_SUCCESS);
ut_ad(mtr.get_savepoint() == 3);
header[0] = mtr.at_savepoint(1);
header[1] = mtr.at_savepoint(2);
ut_ad(header[0]->page.id() == page_id_t(space_id, 0));
ut_ad(header[1]->page.id() == page_id_t(space_id, 1));
/* Block any page writes before the file has been created. */
header[0]->page.lock.x_lock();
header[1]->page.lock.x_lock();
mtr.commit();
/* Durably write the FILE_CREATE record (as well as records for
the fsp_header_init() above before creating the file. */
log_write_up_to(mtr.commit_lsn(), true);
}
DEBUG_SYNC_C("fil_ibd_create_logged");
bool success;
pfs_os_file_t file = os_file_create(
innodb_data_file_key, path, OS_FILE_CREATE,
type, srv_read_only_mode, &success);
ut_ad(!success == (file == OS_FILE_CLOSED));
if (!success) {
*err = DB_ERROR;
/* The following call will print an error message */
switch (os_file_get_last_error(true)) {
case OS_FILE_ALREADY_EXISTS:
sql_print_error("InnoDB: The file '%s'"
" already exists though the"
" corresponding table did not exist"
" in the InnoDB data dictionary."
" You can resolve the problem"
" by removing"
" the file.", path);
*err = DB_TABLESPACE_EXISTS;
break;
case OS_FILE_DISK_FULL:
*err = DB_OUT_OF_FILE_SPACE;
/* fall through */
default:
sql_print_error("InnoDB: Cannot create file '%s'",
path);
}
goto err_exit_after_cleanup;
err_exit:
os_file_delete(innodb_data_file_key, path);
os_file_close(file);
err_exit_after_cleanup:
space->release();
fil_space_free(space_id, false);
space = nullptr;
func_exit:
header[0]->page.lock.x_unlock();
header[1]->page.lock.x_unlock();
DBUG_EXECUTE_IF("checkpoint_after_file_create",
log_make_checkpoint(););
return space;
}
#ifdef _WIN32
const bool is_sparse = is_compressed;
if (is_compressed) {
os_file_set_sparse_win32(file);
}
#else
const bool is_sparse = is_compressed
&& DB_SUCCESS == os_file_punch_hole(file, 0, 4096)
&& !my_test_if_thinly_provisioned(file);
#endif
if (!os_file_set_size(path, file,
os_offset_t(size) << srv_page_size_shift,
is_sparse)) {
*err = DB_OUT_OF_FILE_SPACE;
err_exit:
os_file_close(file);
os_file_delete(innodb_data_file_key, path);
free(crypt_data);
return nullptr;
goto err_exit;
}
fil_space_t::name_type space_name;
DBUG_EXECUTE_IF("fil_space_create_failure",
*err = DB_OUT_OF_FILE_SPACE; goto err_exit;);
if (has_data_dir) {
if (FSP_FLAGS_HAS_DATA_DIR(flags)) {
/* Make the ISL file if the IBD file is not
in the default location. */
space_name = {name.m_name, strlen(name.m_name)};
fil_space_t::name_type space_name{name.m_name,
strlen(name.m_name)};
*err = RemoteDatafile::create_link_file(space_name, path);
if (*err != DB_SUCCESS) {
goto err_exit;
}
}
DBUG_EXECUTE_IF("checkpoint_after_file_create",
log_make_checkpoint(););
mysql_mutex_lock(&fil_system.mutex);
if (fil_space_t* space = fil_space_t::create(space_id,
flags, false,
crypt_data, mode, true)) {
fil_node_t* node = space->add(path, file, size, false, true);
node->find_metadata(IF_WIN(,true));
mysql_mutex_unlock(&fil_system.mutex);
mtr.start();
mtr.set_named_space(space);
ut_a(fsp_header_init(space, size, &mtr) == DB_SUCCESS);
mtr.commit();
return space;
} else {
mysql_mutex_unlock(&fil_system.mutex);
space->clear_stopped();
node->handle = file;
node->find_metadata(IF_WIN(,true));
if (++fil_system.n_open >= srv_max_n_open_files) {
space->reacquire();
fil_space_t::try_to_close(space, true);
space->release();
}
if (space_name.data()) {
RemoteDatafile::delete_link_file(space_name);
}
*err = DB_ERROR;
goto err_exit;
mysql_mutex_unlock(&fil_system.mutex);
goto func_exit;
}
fil_space_t *fil_ibd_open(uint32_t id, uint32_t flags,
@@ -2168,7 +2199,9 @@ func_exit:
|| df_remote.is_open() != df_remote.is_valid()) {
goto corrupted;
}
#ifndef DBUG_OFF
error:
#endif
local_err = DB_ERROR;
goto func_exit;
}
@@ -2192,6 +2225,8 @@ error:
ut_a(valid_tablespaces_found == 1);
skip_validate:
DBUG_EXECUTE_IF("fil_space_create_failure", goto error;);
const byte* first_page =
df_default.is_open() ? df_default.get_first_page() :
df_remote.get_first_page();
@@ -2205,11 +2240,6 @@ skip_validate:
space = fil_space_t::create(id, flags,
validate == fil_space_t::VALIDATE_IMPORT,
crypt_data);
if (!space) {
mysql_mutex_unlock(&fil_system.mutex);
goto error;
}
/* We do not measure the size of the file, that is why
we pass the 0 below */
@@ -2511,11 +2541,6 @@ tablespace_check:
space = fil_space_t::create(uint32_t(space_id), flags, false,
crypt_data);
if (space == NULL) {
mysql_mutex_unlock(&fil_system.mutex);
return(FIL_LOAD_INVALID);
}
ut_ad(space->id == file.space_id());
ut_ad(space->id == space_id);

View File

@@ -112,6 +112,7 @@ Tablespace::open_or_create(bool is_temp)
/* We can close the handle now and open the tablespace
the proper way. */
it->close();
mysql_mutex_lock(&fil_system.mutex);
if (it == begin()) {
/* First data file. */
@@ -130,16 +131,9 @@ Tablespace::open_or_create(bool is_temp)
fsp_flags = FSP_FLAGS_PAGE_SSIZE();
}
mysql_mutex_lock(&fil_system.mutex);
space = fil_space_t::create(
uint32_t(m_space_id), fsp_flags,
false, nullptr);
if (!space) {
mysql_mutex_unlock(&fil_system.mutex);
return DB_ERROR;
}
} else {
mysql_mutex_lock(&fil_system.mutex);
}
space->add(it->m_filepath, OS_FILE_CLOSED, it->m_size,
false, true);

View File

@@ -955,10 +955,6 @@ SysTablespace::open_or_create(
space = fil_space_t::create(
SRV_TMP_SPACE_ID, flags(), false, nullptr);
ut_ad(space == fil_system.temp_space);
if (!space) {
err = DB_ERROR;
break;
}
ut_ad(!space->is_compressed());
ut_ad(space->full_crc32());
} else {
@@ -966,10 +962,6 @@ SysTablespace::open_or_create(
space = fil_space_t::create(
TRX_SYS_SPACE, it->flags(), false, nullptr);
ut_ad(space == fil_system.sys_space);
if (!space) {
err = DB_ERROR;
break;
}
}
uint32_t max_size = (++node_counter == m_files.size()

View File

@@ -607,6 +607,24 @@ public:
n_pending.fetch_and(~NEEDS_FSYNC, std::memory_order_release);
}
/** Set the STOPPING flags when creating a file,
to block premature fil_crypt_find_space_to_rotate() */
inline void set_stopped() noexcept
{
ut_d(uint32_t n=)
n_pending.fetch_add(STOPPING + 1, std::memory_order_relaxed);
ut_ad(n == CLOSING);
}
/** Clear the STOPPING flags after creating a file */
inline void clear_stopped() noexcept
{
ut_d(uint32_t n=)
n_pending.fetch_sub(STOPPING + CLOSING + 1, std::memory_order_relaxed);
ut_ad(n & PENDING);
ut_ad((n & ~PENDING) == (STOPPING | CLOSING));
}
private:
/** Clear the CLOSING flag */
void clear_closing() noexcept
@@ -914,8 +932,7 @@ public:
@param crypt_data encryption information
@param mode encryption mode
@param opened whether the tablespace files are open
@return pointer to created tablespace, to be filled in with add()
@retval nullptr on failure (such as when the same tablespace exists) */
@return pointer to created tablespace, to be filled in with add() */
static fil_space_t *create(uint32_t id, uint32_t flags, bool being_imported,
fil_space_crypt_t *crypt_data,
fil_encryption_t mode= FIL_ENCRYPTION_DEFAULT,
@@ -1081,7 +1098,7 @@ struct fil_node_t final
/** whether the file actually is a raw device or disk partition */
unsigned is_raw_disk:1;
/** whether the tablespace discovery is being deferred during crash
recovery due to incompletely written page 0 */
recovery due to missing file or incompletely written page 0 */
unsigned deferred:1;
/** size of the file in database pages (0 if not known yet);

View File

@@ -647,6 +647,9 @@ struct file_name_t {
/** Status of the tablespace */
fil_status status;
/** Log sequence number of a FILE_CREATE record, or 0 */
lsn_t create_lsn = 0;
/** FSP_SIZE of tablespace */
uint32_t size = 0;
@@ -1297,7 +1300,8 @@ inline size_t recv_sys_t::files_size()
@param[in] name file name
@param[in] len length of the file name
@param[in] space_id the tablespace ID
@param[in] ftype FILE_MODIFY, FILE_DELETE, or FILE_RENAME
@param[in] ftype FILE_CREATE, FILE_MODIFY, FILE_DELETE,
or FILE_RENAME
@param[in] lsn lsn of the redo log
@param[in] if_exists whether to check if the tablespace exists */
static void fil_name_process(const char *name, ulint len, uint32_t space_id,
@@ -1340,6 +1344,7 @@ got_deleted:
}
ut_ad(f.space == NULL);
goto reset_create;
} else if (p.second // the first FILE_MODIFY or FILE_RENAME
|| f.name != fname.name) {
reload:
@@ -1408,6 +1413,10 @@ rename:
break;
}
if (f.create_lsn) {
return;
}
if (srv_force_recovery
|| srv_operation == SRV_OPERATION_RESTORE) {
/* Without innodb_force_recovery,
@@ -1425,7 +1434,7 @@ rename:
int(fname.name.size()),
fname.name.data(), space_id);
}
break;
return;
case FIL_LOAD_DEFER:
if (d && ftype == FILE_RENAME
@@ -1461,6 +1470,10 @@ rename:
" due to innodb_force_recovery",
int(len), name, space_id);
}
reset_create:
f.create_lsn = 0;
} else if (ftype == FILE_CREATE && !f.space) {
f.create_lsn = lsn;
}
}
@@ -2862,7 +2875,7 @@ log_parse_file(const page_id_t id, bool if_exists,
}
fil_name_process(reinterpret_cast<const char*>(l), fnend - l, space_id,
(b & 0xf0) == FILE_DELETE ? FILE_DELETE : FILE_MODIFY,
fn2 ? FILE_MODIFY : mfile_type_t(b & 0xf0),
recv_sys.start_lsn, if_exists);
if (fn2)
@@ -4529,6 +4542,11 @@ next:
case file_name_t::NORMAL:
goto next;
case file_name_t::MISSING:
if (srv_operation != SRV_OPERATION_NORMAL) {
} else if (const lsn_t c = i->second.create_lsn) {
deferred_spaces.add(space, i->second.name, c);
goto next;
}
err = recv_init_missing_space(err, i);
i->second.status = file_name_t::DELETED;
/* fall through */

View File

@@ -675,7 +675,7 @@ bool mtr_t::commit_file(fil_space_t &space, const char *name)
if (!name && space.max_lsn)
{
ut_d(space.max_lsn= 0);
space.max_lsn= 0;
fil_system.named_spaces.remove(space);
}