/** The server header file is included to access opt_initialize global variable. Ifserverpassestheoptionforcreate/openDBtoSE,weshouldremovesuch
direct reference to server header and global variable */ #include"mysqld.h"
/** The control info of the system tablespace. */
SysTablespace srv_sys_space;
/** The control info of a temporary table shared tablespace. */
SysTablespace srv_tmp_space;
/** If the last data file is auto-extended, we add this many pages to it
at a time. We have to make this public because it is a config variable. */
uint sys_tablespace_auto_extend_increment;
/** Convert a numeric string that optionally ends in G or M or K, toanumbercontainingmegabytes. @param[in]strStringwithaquantityinbytes @param[out]megsThenumberinmegabytes
@return next character in string */ char*
SysTablespace::parse_units( char* ptr,
ulint* megs)
{ char* endp;
/*---------------------- PASS 1 ---------------------------*/ /* First calculate the number of data files and check syntax: filepath:size[K|M|G];filepath:size[K|M|G]....
Note that a Windows path may contain a drive name and a ':'. */ while (*str != '\0') {
filepath = str;
ib::error()
<< "syntax error in file path or size" " specified is less than 1 megabyte"; return(false);
}
}
if (n_files == 0) {
/* filepath_spec must contain at least one data file
definition */
ut_free(new_str);
ib::error()
<< "syntax error in file path or size specified" " is less than 1 megabyte";
return(false);
}
/*---------------------- PASS 2 ---------------------------*/ /* Then store the actual values to our arrays */
str = input_str;
ulint order = 0;
while (*str != '\0') {
filepath = str;
/* Note that we must step over the ':' in a Windows filepath; aWindowspathnormallylookslikeC:\ibdata\ibdata1:1G,but aWindowsrawpartitionmayhaveaspecificationlike
\\.\C::1Gnewraw or \\.\PHYSICALDRIVE2:1Gnewraw */
/* Initialize new raw device only during initialize */ /* JAN: TODO: MySQL 5.7 used opt_initialize */
m_files.back().m_type =
opt_bootstrap ? SRV_NEW_RAW : SRV_OLD_RAW;
}
/* Initialize new raw device only during initialize */ if (m_files.back().m_type == SRV_NOT_RAW) { /* JAN: TODO: MySQL 5.7 used opt_initialize */
m_files.back().m_type =
opt_bootstrap ? SRV_NEW_RAW : SRV_OLD_RAW;
}
}
if (*str == ';') {
++str;
}
order++;
}
ut_ad(n_files == ulint(m_files.size()));
ut_free(new_str);
return(true);
}
/** Frees the memory allocated by the parse method. */ void
SysTablespace::shutdown()
{
Tablespace::shutdown();
/** Verify the size of the physical file. @param[in]filedatafileobject
@return DB_SUCCESS if OK else error code. */
dberr_t
SysTablespace::check_size(
Datafile& file)
{
os_offset_t size = os_file_get_size(file.m_handle);
ut_a(size != (os_offset_t) -1);
/* Under some error conditions like disk full scenarios orfilesizereachingfilesystemlimitthedatafile couldcontainanincompleteextentattheend.Whenwe extendadatafileandifsomefailurehappens,then alsothedatafilecouldcontainanincompleteextent.
So we need to round the size downward to a megabyte.*/
/* If last file */ if (&file == &m_files.back() && m_auto_extend_last_file) {
if (file.m_size > rounded_size_pages
|| (m_last_file_size_max > 0
&& m_last_file_size_max < rounded_size_pages)) {
ib::error() << "The Auto-extending data file '"
<< file.filepath()
<< "' is of a different size "
<< rounded_size_pages
<< " pages than specified" " by innodb_data_file_path"; return(DB_ERROR);
}
file.m_size = rounded_size_pages;
}
if (rounded_size_pages != file.m_size) {
ib::error() << "The data file '"
<< file.filepath() << "' is of a different size "
<< rounded_size_pages << " pages" " than the " << file.m_size << " pages specified by" " innodb_data_file_path"; return(DB_ERROR);
}
return(DB_SUCCESS);
}
/** Set the size of the file. @param[in]filedatafileobject
@return DB_SUCCESS or error code */
dberr_t
SysTablespace::set_size(
Datafile& file)
{
ut_ad(!srv_read_only_mode || m_ignore_read_only); const ib::bytes_iec b{uint64_t{file.m_size} << srv_page_size_shift};
/* We created the data file and now write it full of zeros */
ib::info() << "Setting file '" << file.filepath() << "' size to " << b
<< ". Physically writing the file full; Please wait ...";
if (success) {
ib::info() << "File '" << file.filepath() << "' size is now "
<< b
<< ".";
} else {
ib::error() << "Could not set the file size of '"
<< file.filepath() << "'. Probably out of disk space";
return(DB_ERROR);
}
return(DB_SUCCESS);
}
/** Create a data file. @param[in]filedatafileobject
@return DB_SUCCESS or error code */
dberr_t
SysTablespace::create_file(
Datafile& file)
{
dberr_t err = DB_SUCCESS;
/* The partition is opened, not created; then it is
written over */
m_created_new_raw = true;
/* Fall through. */
case SRV_OLD_RAW:
srv_start_raw_disk_in_use = TRUE;
/* Fall through. */
case SRV_NOT_RAW:
err = file.open_or_create(
!m_ignore_read_only && srv_read_only_mode); break;
}
if (err != DB_SUCCESS) { return err;
}
switch (file.m_type) { case SRV_OLD_RAW: break; case SRV_NOT_RAW: #ifndef _WIN32 if (!space_id() && my_disable_locking
&& os_file_lock(file.m_handle, file.m_filepath)) {
err = DB_ERROR; break;
} #endif /* fall through */ case SRV_NEW_RAW:
err = set_size(file);
}
return(err);
}
/** Open a data file. @param[in]filedatafileobject
@return DB_SUCCESS or error code */
dberr_t
SysTablespace::open_file(
Datafile& file)
{
dberr_t err = DB_SUCCESS;
ut_a(file.m_exists);
switch (file.m_type) { case SRV_NEW_RAW: /* The partition is opened, not created; then it is
written over */
m_created_new_raw = true;
/* Fall through */
case SRV_OLD_RAW:
srv_start_raw_disk_in_use = TRUE;
if (srv_read_only_mode && !m_ignore_read_only) {
ib::error() << "Can't open a raw device '"
<< file.m_filepath << "' when" " --innodb-read-only is set";
return(DB_ERROR);
}
/* Fall through */
case SRV_NOT_RAW:
err = file.open_or_create(
!m_ignore_read_only && srv_read_only_mode);
if (err != DB_SUCCESS) { return(err);
} break;
}
switch (file.m_type) { case SRV_NEW_RAW: /* Set file size for new raw device. */
err = set_size(file); break;
/** Check the tablespace header for this tablespace.
@return DB_SUCCESS or error code */ inline dberr_t SysTablespace::read_lsn_and_check_flags()
{
dberr_t err;
if (srv_operation <= SRV_OPERATION_EXPORT_RESTORED) {
buf_dblwr.init_or_load_pages(it->handle(), it->filepath());
}
/* Check the contents of the first page of the
first datafile. */
err = it->validate_first_page(it->m_first_page); const page_t *first_page = it->m_first_page;
/* Make sure the tablespace space ID matches the
space ID on the first page of the first datafile. */ if (err != DB_SUCCESS || space_id() != it->m_space_id) {
sql_print_error("InnoDB: The data file '%s'" " has the wrong space ID." " It should be " UINT32PF ", but " UINT32PF " was found", it->filepath(),
space_id(), it->m_space_id);
it->close(); return err;
}
if (!log_sys.file_size && log_sys.format == log_t::FORMAT_3_23
&& srv_operation == SRV_OPERATION_NORMAL
&& srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
log_sys.latch.wr_lock(); /* Upgrade from 0-sized ib_logfile0. */
log_sys.last_checkpoint_lsn = mach_read_from_8(
first_page + 26/*FIL_PAGE_FILE_FLUSH_LSN*/); if (log_sys.last_checkpoint_lsn < 8204) { /* Before MDEV-14425, InnoDB had a minimum LSN of8192+12=8204.Likewise,mariadb-backup --preparewouldcreateanemptyib_logfile0 afterapplyingthelog.Wewillallowan
upgrade from such an empty log. */
sql_print_error("InnoDB: ib_logfile0 is " "empty, and LSN is unknown.");
err = DB_CORRUPTION;
} else {
recv_sys.lsn = recv_sys.file_checkpoint =
log_sys.last_checkpoint_lsn;
log_sys.set_recovered_lsn(recv_sys.lsn);
log_sys.next_checkpoint_no = 0;
}
log_sys.latch.wr_unlock();
}
it->close(); return err;
}
/** Check if a file can be opened in the correct mode. @param[in]filedatafileobject @param[out]reasonexactreasoniffile_statuscheckfailed.
@return DB_SUCCESS or error code. */
dberr_t
SysTablespace::check_file_status( const Datafile& file,
file_status_t& reason)
{
os_file_stat_t stat;
reason = FILE_STATUS_VOID; /* File exists but we can't read the rw-permission settings. */ switch (err) { case DB_FAIL:
ib::error() << "os_file_get_status() failed on '"
<< file.filepath()
<< "'. Can't determine file permissions";
err = DB_ERROR;
reason = FILE_STATUS_RW_PERMISSION_ERROR; break;
case DB_SUCCESS: /* Note: stat.rw_perm is only valid for "regular" files */
if (stat.type == OS_FILE_TYPE_FILE) { if (!stat.rw_perm) {
ib::error() << "The data file"
<< " '" << file.filepath()
<< ((!srv_read_only_mode
|| m_ignore_read_only)
? "' must be writable"
: "' must be readable");
/** Note that the data file was not found. @param[in]filedatafileobject @param[out]create_new_dbtrueifanewinstancetobecreated
@return DB_SUCESS or error code */
dberr_t
SysTablespace::file_not_found(
Datafile& file, bool* create_new_db)
{
file.m_exists = false;
if (m_ignore_read_only) {
} elseif (srv_read_only_mode) {
ib::error() << "Can't create file '" << file.filepath()
<< "' when --innodb-read-only is set"; return(DB_ERROR);
} elseif (srv_force_recovery && space_id() == TRX_SYS_SPACE) {
ib::error() << "Can't create file '" << file.filepath()
<< "' when --innodb-force-recovery is set"; return DB_ERROR;
}
if (&file == &m_files.front()) {
/* First data file. */
ut_a(!*create_new_db);
*create_new_db = TRUE;
if (space_id() == TRX_SYS_SPACE) {
ib::info() << "The first data file '"
<< file.filepath() << "' did not exist." " A new tablespace will be created!";
}
} else {
ib::info() << "Need to create a new data file '"
<< file.filepath() << "'.";
}
/* Set the file create mode. */ switch (file.m_type) { case SRV_NOT_RAW:
file.set_open_flags(OS_FILE_CREATE); break;
case SRV_NEW_RAW: case SRV_OLD_RAW:
file.set_open_flags(OS_FILE_OPEN_RAW); break;
}
return(DB_SUCCESS);
}
/** Note that the data file was found. @param[in,out]filedatafileobject
@return true if a new instance to be created */ bool
SysTablespace::file_found(
Datafile& file)
{ /* Note that the file exists and can be opened
in the appropriate mode. */
file.m_exists = true;
/* Set the file open mode */ switch (file.m_type) { case SRV_NOT_RAW:
file.set_open_flags(
&file == &m_files.front()
? OS_FILE_OPEN_RETRY : OS_FILE_OPEN); break;
case SRV_NEW_RAW: case SRV_OLD_RAW:
file.set_open_flags(OS_FILE_OPEN_RAW); break;
}
/* Need to create the system tablespace for new raw device. */ return(file.m_type == SRV_NEW_RAW);
}
/** Check the data file specification. @param[out]create_new_dbtrueifanewdatabaseistobecreated @param[in]min_expected_sizeMinimumexpectedtablespacesizeinbytes
@return DB_SUCCESS if all OK else error code */
dberr_t
SysTablespace::check_file_spec( bool* create_new_db,
ulint min_expected_size)
{
*create_new_db = FALSE;
if (m_files.size() >= 1000) {
ib::error() << "There must be < 1000 data files " " but " << m_files.size() << " have been" " defined.";
return(DB_ERROR);
}
if (!m_auto_extend_last_file
&& get_sum_of_sizes()
< (min_expected_size >> srv_page_size_shift)) {
ib::error() << "Tablespace size must be at least "
<< (min_expected_size >> 20) << " MB"; return(DB_ERROR);
}
dberr_t err = DB_SUCCESS;
ut_a(!m_files.empty());
/* If there is more than one data file and the last data file
doesn't exist, that is OK. We allow adding of new data files. */
files_t::iterator begin = m_files.begin();
files_t::iterator end = m_files.end();
for (files_t::iterator it = begin; it != end; ++it) {
} elseif (err != DB_SUCCESS) { if (reason_if_failed == FILE_STATUS_READ_WRITE_ERROR) {
ib::error() << "The data file '"
<< it->filepath()
<< ((!srv_read_only_mode
|| m_ignore_read_only)
? "' must be writable"
: "' must be readable");
}
ut_a(err != DB_FAIL); break;
} elseif (*create_new_db) {
ib::error() << "The data file '"
<< begin->filepath()
<< "' was not found but" " one of the other data files '"
<< it->filepath() << "' exists.";
err = DB_ERROR; break;
} else {
*create_new_db = file_found(*it);
}
}
return(err);
}
/** Open or create the data files @param[in]is_tempwhetherthisisatemporarytablespace @param[in]create_new_dbwhetherwearecreatinganewdatabase @param[out]sum_new_sizessumofsizesofthenewfilesadded
@return DB_SUCCESS or error code */
dberr_t
SysTablespace::open_or_create( bool is_temp, bool create_new_db,
ulint* sum_new_sizes)
{
dberr_t err = DB_SUCCESS;
fil_space_t* space = NULL;
ut_ad(!m_files.empty());
if (sum_new_sizes) {
*sum_new_sizes = 0;
}
files_t::iterator begin = m_files.begin();
files_t::iterator end = m_files.end();
ut_ad(begin->order() == 0);
for (files_t::iterator it = begin; it != end; ++it) {
if (it->m_exists) {
err = open_file(*it);
/* For new raw device increment new size. */ if (sum_new_sizes && it->m_type == SRV_NEW_RAW) {
*sum_new_sizes += it->m_size;
}
} else {
err = create_file(*it);
if (sum_new_sizes) {
*sum_new_sizes += it->m_size;
}
/* Set the correct open flags now that we have
successfully created the file. */ if (err == DB_SUCCESS) { /* We ignore new_db OUT parameter here
as the information is known at this stage */
file_found(*it);
}
}
if (err != DB_SUCCESS) { return(err);
}
}
if (!create_new_db && space_id() == TRX_SYS_SPACE) { /* Validate the header page in the first datafile. */
err = read_lsn_and_check_flags(); if (err != DB_SUCCESS) { return(err);
}
}
/* Close the current handles, add space and file info to the fil_systemcacheandtheDataDictionary,andre-openthem
in fil_system cache so that they stay open until shutdown. */
mysql_mutex_lock(&fil_system.mutex);
ulint node_counter = 0; for (files_t::iterator it = begin; it != end; ++it) {
it->close();
it->m_exists = true;
/** Normalize the file size, convert from megabytes to number of pages. */ void
SysTablespace::normalize_size()
{
files_t::iterator end = m_files.end();
for (files_t::iterator it = m_files.begin(); it != end; ++it) {
/**
@return next increment size */
uint32_t SysTablespace::get_increment() const
{ if (m_last_file_size_max == 0) return get_autoextend_increment();
if (!is_valid_size())
{
ib::error() << "The last data file has a size of " << last_file_size()
<< " but the max size allowed is "
<< m_last_file_size_max;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.