summaryrefslogtreecommitdiff
path: root/storage/innobase
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase')
-rw-r--r--storage/innobase/btr/btr0cur.cc4
-rw-r--r--storage/innobase/buf/buf0buf.cc10
-rw-r--r--storage/innobase/buf/buf0dblwr.cc42
-rw-r--r--storage/innobase/buf/buf0flu.cc54
-rw-r--r--storage/innobase/buf/buf0lru.cc9
-rw-r--r--storage/innobase/buf/buf0rea.cc27
-rw-r--r--storage/innobase/fil/fil0fil.cc25
-rw-r--r--storage/innobase/fsp/fsp0file.cc2
-rw-r--r--storage/innobase/fsp/fsp0sysspace.cc2
-rw-r--r--storage/innobase/handler/ha_innodb.cc92
-rw-r--r--storage/innobase/handler/i_s.cc8
-rw-r--r--storage/innobase/include/buf0buf.h16
-rw-r--r--storage/innobase/include/buf0dblwr.h40
-rw-r--r--storage/innobase/include/fil0fil.h3
-rw-r--r--storage/innobase/include/ha_prototypes.h10
-rw-r--r--storage/innobase/include/log0log.h1
-rw-r--r--storage/innobase/include/os0file.h22
-rw-r--r--storage/innobase/include/srv0srv.h3
-rw-r--r--storage/innobase/log/log0recv.cc23
-rw-r--r--storage/innobase/os/os0file.cc66
-rw-r--r--storage/innobase/page/page0zip.cc5
-rw-r--r--storage/innobase/rem/rem0cmp.cc5
-rw-r--r--storage/innobase/rem/rem0rec.cc6
-rw-r--r--storage/innobase/row/row0import.cc1
-rw-r--r--storage/innobase/row/row0ins.cc48
-rw-r--r--storage/innobase/row/row0vers.cc28
-rw-r--r--storage/innobase/srv/srv0start.cc33
27 files changed, 272 insertions, 313 deletions
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index dda6a95da16..a33f8f0ee43 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -1059,7 +1059,7 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode,
if (lock_intention == BTR_INTENTION_DELETE)
{
compress_limit= BTR_CUR_PAGE_COMPRESS_LIMIT(index());
- if (buf_pool.n_pend_reads &&
+ if (os_aio_pending_reads_approx() &&
trx_sys.history_size_approx() > BTR_CUR_FINE_HISTORY_LENGTH)
{
/* Most delete-intended operations are due to the purge of history.
@@ -1844,7 +1844,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
{
compress_limit= BTR_CUR_PAGE_COMPRESS_LIMIT(index);
- if (buf_pool.n_pend_reads &&
+ if (os_aio_pending_reads_approx() &&
trx_sys.history_size_approx() > BTR_CUR_FINE_HISTORY_LENGTH)
{
mtr_x_lock_index(index, mtr);
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 031270a05d3..6308ea0b5dc 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -3528,9 +3528,6 @@ dberr_t buf_page_t::read_complete(const fil_node_t &node)
ut_ad(zip_size() == node.space->zip_size());
ut_ad(!!zip.ssize == !!zip.data);
- ut_d(auto n=) buf_pool.n_pend_reads--;
- ut_ad(n > 0);
-
const byte *read_frame= zip.data ? zip.data : frame;
ut_ad(read_frame);
@@ -3830,9 +3827,8 @@ void buf_pool_t::print()
<< ", modified database pages="
<< UT_LIST_GET_LEN(flush_list)
<< ", n pending decompressions=" << n_pend_unzip
- << ", n pending reads=" << n_pend_reads
<< ", n pending flush LRU=" << n_flush()
- << " list=" << buf_dblwr.pending_writes()
+ << " list=" << os_aio_pending_writes()
<< ", pages made young=" << stat.n_pages_made_young
<< ", not young=" << stat.n_pages_not_made_young
<< ", pages read=" << stat.n_pages_read
@@ -3945,11 +3941,11 @@ void buf_stats_get_pool_info(buf_pool_info_t *pool_info)
pool_info->n_pend_unzip = UT_LIST_GET_LEN(buf_pool.unzip_LRU);
- pool_info->n_pend_reads = buf_pool.n_pend_reads;
+ pool_info->n_pend_reads = os_aio_pending_reads_approx();
pool_info->n_pending_flush_lru = buf_pool.n_flush();
- pool_info->n_pending_flush_list = buf_dblwr.pending_writes();
+ pool_info->n_pending_flush_list = os_aio_pending_writes();
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
current_time = time(NULL);
diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc
index 8d8b92ae560..c5de7a41808 100644
--- a/storage/innobase/buf/buf0dblwr.cc
+++ b/storage/innobase/buf/buf0dblwr.cc
@@ -53,7 +53,6 @@ void buf_dblwr_t::init()
active_slot= &slots[0];
mysql_mutex_init(buf_dblwr_mutex_key, &mutex, nullptr);
pthread_cond_init(&cond, nullptr);
- pthread_cond_init(&write_cond, nullptr);
}
}
@@ -467,7 +466,6 @@ void buf_dblwr_t::close()
ut_ad(!batch_running);
pthread_cond_destroy(&cond);
- pthread_cond_destroy(&write_cond);
for (int i= 0; i < 2; i++)
{
aligned_free(slots[i].write_buf);
@@ -479,38 +477,31 @@ void buf_dblwr_t::close()
}
/** Update the doublewrite buffer on write completion. */
-void buf_dblwr_t::write_completed(bool with_doublewrite)
+void buf_dblwr_t::write_completed()
{
ut_ad(this == &buf_dblwr);
ut_ad(!srv_read_only_mode);
mysql_mutex_lock(&mutex);
- ut_ad(writes_pending);
- if (!--writes_pending)
- pthread_cond_broadcast(&write_cond);
+ ut_ad(is_created());
+ ut_ad(srv_use_doublewrite_buf);
+ ut_ad(batch_running);
+ slot *flush_slot= active_slot == &slots[0] ? &slots[1] : &slots[0];
+ ut_ad(flush_slot->reserved);
+ ut_ad(flush_slot->reserved <= flush_slot->first_free);
- if (with_doublewrite)
+ if (!--flush_slot->reserved)
{
- ut_ad(is_created());
- ut_ad(srv_use_doublewrite_buf);
- ut_ad(batch_running);
- slot *flush_slot= active_slot == &slots[0] ? &slots[1] : &slots[0];
- ut_ad(flush_slot->reserved);
- ut_ad(flush_slot->reserved <= flush_slot->first_free);
-
- if (!--flush_slot->reserved)
- {
- mysql_mutex_unlock(&mutex);
- /* This will finish the batch. Sync data files to the disk. */
- fil_flush_file_spaces();
- mysql_mutex_lock(&mutex);
+ mysql_mutex_unlock(&mutex);
+ /* This will finish the batch. Sync data files to the disk. */
+ fil_flush_file_spaces();
+ mysql_mutex_lock(&mutex);
- /* We can now reuse the doublewrite memory buffer: */
- flush_slot->first_free= 0;
- batch_running= false;
- pthread_cond_broadcast(&cond);
- }
+ /* We can now reuse the doublewrite memory buffer: */
+ flush_slot->first_free= 0;
+ batch_running= false;
+ pthread_cond_broadcast(&cond);
}
mysql_mutex_unlock(&mutex);
@@ -754,7 +745,6 @@ void buf_dblwr_t::add_to_batch(const IORequest &request, size_t size)
const ulint buf_size= 2 * block_size();
mysql_mutex_lock(&mutex);
- writes_pending++;
for (;;)
{
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index 3fa26dab25f..b702d79df8b 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -209,7 +209,7 @@ void buf_flush_remove_pages(uint32_t id)
if (!deferred)
break;
- buf_dblwr.wait_for_page_writes();
+ os_aio_wait_until_no_pending_writes();
}
}
@@ -339,9 +339,9 @@ void buf_page_write_complete(const IORequest &request)
if (request.is_LRU())
{
const bool temp= bpage->oldest_modification() == 2;
- if (!temp)
- buf_dblwr.write_completed(state < buf_page_t::WRITE_FIX_REINIT &&
- request.node->space->use_doublewrite());
+ if (!temp && state < buf_page_t::WRITE_FIX_REINIT &&
+ request.node->space->use_doublewrite())
+ buf_dblwr.write_completed();
/* We must hold buf_pool.mutex while releasing the block, so that
no other thread can access it before we have freed it. */
mysql_mutex_lock(&buf_pool.mutex);
@@ -353,8 +353,9 @@ void buf_page_write_complete(const IORequest &request)
}
else
{
- buf_dblwr.write_completed(state < buf_page_t::WRITE_FIX_REINIT &&
- request.node->space->use_doublewrite());
+ if (state < buf_page_t::WRITE_FIX_REINIT &&
+ request.node->space->use_doublewrite())
+ buf_dblwr.write_completed();
bpage->write_complete(false);
}
}
@@ -847,8 +848,6 @@ bool buf_page_t::flush(bool evict, fil_space_t *space)
ut_ad(lsn >= oldest_modification());
log_write_up_to(lsn, true);
}
- if (UNIV_LIKELY(space->purpose != FIL_TYPE_TEMPORARY))
- buf_dblwr.add_unbuffered();
space->io(IORequest{type, this, slot}, physical_offset(), size,
write_frame, this);
}
@@ -1083,13 +1082,11 @@ static ulint buf_flush_try_neighbors(fil_space_t *space,
mysql_mutex_unlock(&buf_pool.mutex);
}
- ut_ad(!bpage);
-
- if (auto n= count - 1)
+ if (count > 1)
{
MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_NEIGHBOR_TOTAL_PAGE,
MONITOR_FLUSH_NEIGHBOR_COUNT,
- MONITOR_FLUSH_NEIGHBOR_PAGES, n);
+ MONITOR_FLUSH_NEIGHBOR_PAGES, count - 1);
}
return count;
@@ -1964,7 +1961,7 @@ static void buf_flush_wait(lsn_t lsn)
break;
}
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
- buf_dblwr.wait_for_page_writes();
+ os_aio_wait_until_no_pending_writes();
mysql_mutex_lock(&buf_pool.flush_list_mutex);
}
}
@@ -1985,8 +1982,6 @@ ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn)
if (buf_pool.get_oldest_modification(sync_lsn) < sync_lsn)
{
MONITOR_INC(MONITOR_FLUSH_SYNC_WAITS);
- thd_wait_begin(nullptr, THD_WAIT_DISKIO);
- tpool::tpool_wait_begin();
#if 1 /* FIXME: remove this, and guarantee that the page cleaner serves us */
if (UNIV_UNLIKELY(!buf_page_cleaner_is_active))
@@ -2001,7 +1996,7 @@ ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn)
MONITOR_FLUSH_SYNC_COUNT,
MONITOR_FLUSH_SYNC_PAGES, n_pages);
}
- buf_dblwr.wait_for_page_writes();
+ os_aio_wait_until_no_pending_writes();
mysql_mutex_lock(&buf_pool.flush_list_mutex);
}
while (buf_pool.get_oldest_modification(sync_lsn) < sync_lsn);
@@ -2010,7 +2005,6 @@ ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn)
#endif
buf_flush_wait(sync_lsn);
- tpool::tpool_wait_end();
thd_wait_end(nullptr);
}
@@ -2375,7 +2369,7 @@ static void buf_flush_page_cleaner()
if (!recv_recovery_is_on() &&
!srv_startup_is_before_trx_rollback_phase &&
- srv_operation == SRV_OPERATION_NORMAL)
+ srv_operation <= SRV_OPERATION_EXPORT_RESTORED)
log_checkpoint();
}
while (false);
@@ -2445,7 +2439,7 @@ static void buf_flush_page_cleaner()
last_activity_count= activity_count;
goto maybe_unemployed;
}
- else if (buf_pool.page_cleaner_idle() && buf_pool.n_pend_reads == 0)
+ else if (buf_pool.page_cleaner_idle() && !os_aio_pending_reads())
{
/* reaching here means 3 things:
- last_activity_count == activity_count: suggesting server is idle
@@ -2521,7 +2515,7 @@ static void buf_flush_page_cleaner()
mysql_mutex_lock(&buf_pool.flush_list_mutex);
buf_flush_wait_LRU_batch_end();
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
- buf_dblwr.wait_for_page_writes();
+ os_aio_wait_until_no_pending_writes();
}
mysql_mutex_lock(&buf_pool.flush_list_mutex);
@@ -2547,7 +2541,7 @@ static void buf_flush_page_cleaner()
ATTRIBUTE_COLD void buf_flush_page_cleaner_init()
{
ut_ad(!buf_page_cleaner_is_active);
- ut_ad(srv_operation == SRV_OPERATION_NORMAL ||
+ ut_ad(srv_operation <= SRV_OPERATION_EXPORT_RESTORED ||
srv_operation == SRV_OPERATION_RESTORE ||
srv_operation == SRV_OPERATION_RESTORE_EXPORT);
buf_flush_async_lsn= 0;
@@ -2571,15 +2565,7 @@ ATTRIBUTE_COLD void buf_flush_buffer_pool()
{
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
buf_flush_list(srv_max_io_capacity);
- if (const size_t pending= buf_dblwr.pending_writes())
- {
- timespec abstime;
- service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL,
- "Waiting to write %zu pages", pending);
- set_timespec(abstime, INNODB_EXTEND_TIMEOUT_INTERVAL / 2);
- buf_dblwr.wait_for_page_writes(abstime);
- }
-
+ os_aio_wait_until_no_pending_writes();
mysql_mutex_lock(&buf_pool.flush_list_mutex);
service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL,
"Waiting to flush " ULINTPF " pages",
@@ -2587,20 +2573,18 @@ ATTRIBUTE_COLD void buf_flush_buffer_pool()
}
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
- ut_ad(!buf_pool.any_io_pending());
+ ut_ad(!os_aio_pending_writes());
+ ut_ad(!os_aio_pending_reads());
}
/** Synchronously flush dirty blocks during recv_sys_t::apply().
NOTE: The calling thread is not allowed to hold any buffer page latches! */
void buf_flush_sync_batch(lsn_t lsn)
{
- thd_wait_begin(nullptr, THD_WAIT_DISKIO);
- tpool::tpool_wait_begin();
+ lsn= std::max(lsn, log_sys.get_lsn());
mysql_mutex_lock(&buf_pool.flush_list_mutex);
buf_flush_wait(lsn);
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
- tpool::tpool_wait_end();
- thd_wait_end(nullptr);
}
/** Synchronously flush dirty blocks.
diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc
index 2e9b42e9f51..d1c7f0ba666 100644
--- a/storage/innobase/buf/buf0lru.cc
+++ b/storage/innobase/buf/buf0lru.cc
@@ -1112,17 +1112,8 @@ static bool buf_LRU_block_remove_hashed(buf_page_t *bpage, const page_id_t id,
break;
case FIL_PAGE_TYPE_ZBLOB:
case FIL_PAGE_TYPE_ZBLOB2:
- break;
case FIL_PAGE_INDEX:
case FIL_PAGE_RTREE:
-#if defined UNIV_ZIP_DEBUG && defined BTR_CUR_HASH_ADAPT
- /* During recovery, we only update the
- compressed page, not the uncompressed one. */
- ut_a(recv_recovery_is_on()
- || page_zip_validate(
- &bpage->zip, page,
- ((buf_block_t*) bpage)->index));
-#endif /* UNIV_ZIP_DEBUG && BTR_CUR_HASH_ADAPT */
break;
default:
ib::error() << "The compressed page to be"
diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc
index fa91939acee..8631a03644f 100644
--- a/storage/innobase/buf/buf0rea.cc
+++ b/storage/innobase/buf/buf0rea.cc
@@ -227,12 +227,9 @@ static buf_page_t* buf_page_init_for_read(ulint mode, const page_id_t page_id,
}
buf_pool.stat.n_pages_read++;
- mysql_mutex_unlock(&buf_pool.mutex);
- buf_pool.n_pend_reads++;
- goto func_exit_no_mutex;
func_exit:
mysql_mutex_unlock(&buf_pool.mutex);
-func_exit_no_mutex:
+
if (mode == BUF_READ_IBUF_PAGES_ONLY)
ibuf_mtr_commit(&mtr);
@@ -319,8 +316,6 @@ buf_read_page_low(
page_id.page_no() * len, len, dst, bpage);
if (UNIV_UNLIKELY(fio.err != DB_SUCCESS)) {
- ut_d(auto n=) buf_pool.n_pend_reads--;
- ut_ad(n > 0);
buf_pool.corrupted_evict(bpage, buf_page_t::READ_FIX);
} else if (sync) {
thd_wait_end(NULL);
@@ -367,7 +362,8 @@ buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf)
read-ahead, as that could break the ibuf page access order */
return 0;
- if (buf_pool.n_pend_reads > buf_pool.curr_size / BUF_READ_AHEAD_PEND_LIMIT)
+ if (os_aio_pending_reads_approx() >
+ buf_pool.curr_size / BUF_READ_AHEAD_PEND_LIMIT)
return 0;
fil_space_t* space= fil_space_t::get(page_id.space());
@@ -519,7 +515,8 @@ buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf)
/* No read-ahead to avoid thread deadlocks */
return 0;
- if (buf_pool.n_pend_reads > buf_pool.curr_size / BUF_READ_AHEAD_PEND_LIMIT)
+ if (os_aio_pending_reads_approx() >
+ buf_pool.curr_size / BUF_READ_AHEAD_PEND_LIMIT)
return 0;
const uint32_t buf_read_ahead_area= buf_pool.read_ahead_area;
@@ -687,18 +684,8 @@ void buf_read_recv_pages(uint32_t space_id, st_::span<uint32_t> page_nos)
limit += buf_pool.chunks[j].size / 2;
}
- for (ulint count = 0; buf_pool.n_pend_reads >= limit; ) {
- std::this_thread::sleep_for(
- std::chrono::milliseconds(10));
-
- if (!(++count % 1000)) {
-
- ib::error()
- << "Waited for " << count / 100
- << " seconds for "
- << buf_pool.n_pend_reads
- << " pending reads";
- }
+ if (os_aio_pending_reads() >= limit) {
+ os_aio_wait_until_no_pending_reads();
}
space->reacquire();
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index a3d9df4af1b..24319bcb8a6 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -97,7 +97,13 @@ bool fil_space_t::try_to_close(bool print_info)
if (!node->is_open())
continue;
- if (const auto n= space.set_closing())
+ /* Other thread is trying to do fil_delete_tablespace()
+ concurrently for the same tablespace. So ignore this
+ tablespace and try to close the other one */
+ const auto n= space.set_closing();
+ if (n & STOPPING)
+ continue;
+ if (n & (PENDING | NEEDS_FSYNC))
{
if (!print_info)
continue;
@@ -1370,7 +1376,10 @@ void fil_space_t::close_all()
for (ulint count= 10000; count--;)
{
- if (!space.set_closing())
+ const auto n= space.set_closing();
+ if (n & STOPPING)
+ goto next;
+ if (!(n & (PENDING | NEEDS_FSYNC)))
{
node->close();
goto next;
@@ -2060,6 +2069,10 @@ func_exit:
must_validate = true;
}
+ const bool operation_not_for_export =
+ srv_operation != SRV_OPERATION_RESTORE_EXPORT
+ && srv_operation != SRV_OPERATION_EXPORT_RESTORED;
+
/* Always look for a file at the default location. But don't log
an error if the tablespace is already open in remote or dict. */
ut_a(df_default.filepath());
@@ -2070,6 +2083,7 @@ func_exit:
drop_garbage_tables_after_restore() a little later. */
const bool strict = validate && !tablespaces_found
+ && operation_not_for_export
&& !(srv_operation == SRV_OPERATION_NORMAL
&& srv_start_after_restore
&& srv_force_recovery < SRV_FORCE_NO_BACKGROUND
@@ -2118,7 +2132,11 @@ func_exit:
goto corrupted;
}
- os_file_get_last_error(true);
+ os_file_get_last_error(operation_not_for_export,
+ !operation_not_for_export);
+ if (!operation_not_for_export) {
+ goto corrupted;
+ }
sql_print_error("InnoDB: Could not find a valid tablespace"
" file for %.*s. %s",
static_cast<int>(name.size()), name.data(),
@@ -2285,6 +2303,7 @@ fil_ibd_discover(
case SRV_OPERATION_RESTORE:
break;
case SRV_OPERATION_NORMAL:
+ case SRV_OPERATION_EXPORT_RESTORED:
size_t len= strlen(db);
if (len <= 4 || strcmp(db + len - 4, dot_ext[IBD])) {
break;
diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc
index 0a4119587f8..e93ca4bc177 100644
--- a/storage/innobase/fsp/fsp0file.cc
+++ b/storage/innobase/fsp/fsp0file.cc
@@ -756,7 +756,7 @@ the double write buffer.
bool
Datafile::restore_from_doublewrite()
{
- if (srv_operation != SRV_OPERATION_NORMAL) {
+ if (srv_operation > SRV_OPERATION_EXPORT_RESTORED) {
return true;
}
diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc
index ef650436907..09eea04b655 100644
--- a/storage/innobase/fsp/fsp0sysspace.cc
+++ b/storage/innobase/fsp/fsp0sysspace.cc
@@ -576,7 +576,7 @@ inline dberr_t SysTablespace::read_lsn_and_check_flags()
ut_a(it->order() == 0);
- if (srv_operation == SRV_OPERATION_NORMAL) {
+ if (srv_operation <= SRV_OPERATION_EXPORT_RESTORED) {
buf_dblwr.init_or_load_pages(it->handle(), it->filepath());
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 63210741466..f11ac9a05b6 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -545,6 +545,7 @@ mysql_pfs_key_t trx_pool_manager_mutex_key;
mysql_pfs_key_t lock_wait_mutex_key;
mysql_pfs_key_t trx_sys_mutex_key;
mysql_pfs_key_t srv_threads_mutex_key;
+mysql_pfs_key_t tpool_cache_mutex_key;
/* all_innodb_mutexes array contains mutexes that are
performance schema instrumented if "UNIV_PFS_MUTEX"
@@ -578,6 +579,7 @@ static PSI_mutex_info all_innodb_mutexes[] = {
PSI_KEY(rtr_match_mutex),
PSI_KEY(rtr_path_mutex),
PSI_KEY(trx_sys_mutex),
+ PSI_KEY(tpool_cache_mutex),
};
# endif /* UNIV_PFS_MUTEX */
@@ -2077,7 +2079,7 @@ static void innodb_ddl_recovery_done(handlerton*)
{
ut_ad(!ddl_recovery_done);
ut_d(ddl_recovery_done= true);
- if (!srv_read_only_mode && srv_operation == SRV_OPERATION_NORMAL &&
+ if (!srv_read_only_mode && srv_operation <= SRV_OPERATION_EXPORT_RESTORED &&
srv_force_recovery < SRV_FORCE_NO_BACKGROUND)
{
if (srv_start_after_restore && !high_level_read_only)
@@ -8479,6 +8481,37 @@ wsrep_calc_row_hash(
return(0);
}
+
+/** Append table-level exclusive key.
+@param thd MySQL thread handle
+@param table table
+@retval false on success
+@retval true on failure */
+ATTRIBUTE_COLD bool wsrep_append_table_key(MYSQL_THD thd, const dict_table_t &table)
+{
+ char db_buf[NAME_LEN + 1];
+ char tbl_buf[NAME_LEN + 1];
+ ulint db_buf_len, tbl_buf_len;
+
+ if (!table.parse_name(db_buf, tbl_buf, &db_buf_len, &tbl_buf_len))
+ {
+ WSREP_ERROR("Parse_name for table key append failed: %s",
+ wsrep_thd_query(thd));
+ return true;
+ }
+
+ /* Append table-level exclusive key */
+ const int rcode = wsrep_thd_append_table_key(thd, db_buf,
+ tbl_buf, WSREP_SERVICE_KEY_EXCLUSIVE);
+ if (rcode)
+ {
+ WSREP_ERROR("Appending table key failed: %s, %d",
+ wsrep_thd_query(thd), rcode);
+ return true;
+ }
+
+ return false;
+}
#endif /* WITH_WSREP */
/**
@@ -8649,11 +8682,16 @@ func_exit:
&& !wsrep_thd_ignore_table(m_user_thd)) {
DBUG_PRINT("wsrep", ("update row key"));
- if (wsrep_append_keys(m_user_thd,
- wsrep_protocol_version >= 4
- ? WSREP_SERVICE_KEY_UPDATE
- : WSREP_SERVICE_KEY_EXCLUSIVE,
- old_row, new_row)){
+ /* We use table-level exclusive key for SEQUENCES
+ and normal key append for others. */
+ if (table->s->table_type == TABLE_TYPE_SEQUENCE) {
+ if (wsrep_append_table_key(m_user_thd, *m_prebuilt->table))
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+ } else if (wsrep_append_keys(m_user_thd,
+ wsrep_protocol_version >= 4
+ ? WSREP_SERVICE_KEY_UPDATE
+ : WSREP_SERVICE_KEY_EXCLUSIVE,
+ old_row, new_row)) {
WSREP_DEBUG("WSREP: UPDATE_ROW_KEY FAILED");
DBUG_PRINT("wsrep", ("row key failed"));
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
@@ -17917,44 +17955,6 @@ exit:
return;
}
-/** Validate SET GLOBAL innodb_buffer_pool_filename.
-On Windows, file names with colon (:) are not allowed.
-@param thd connection
-@param save &srv_buf_dump_filename
-@param value new value to be validated
-@return 0 for valid name */
-static int innodb_srv_buf_dump_filename_validate(THD *thd, st_mysql_sys_var*,
- void *save,
- st_mysql_value *value)
-{
- char buff[OS_FILE_MAX_PATH];
- int len= sizeof buff;
-
- if (const char *buf_name= value->val_str(value, buff, &len))
- {
-#ifdef _WIN32
- if (!is_filename_allowed(buf_name, len, FALSE))
- {
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_WRONG_ARGUMENTS,
- "InnoDB: innodb_buffer_pool_filename "
- "cannot have colon (:) in the file name.");
- return 1;
- }
-#endif /* _WIN32 */
- if (buf_name == buff)
- {
- ut_ad(static_cast<size_t>(len) < sizeof buff);
- buf_name= thd_strmake(thd, buf_name, len);
- }
-
- *static_cast<const char**>(save)= buf_name;
- return 0;
- }
-
- return 1;
-}
-
#ifdef UNIV_DEBUG
static char* srv_buffer_pool_evict;
@@ -19057,9 +19057,9 @@ static MYSQL_SYSVAR_SIZE_T(buffer_pool_chunk_size, srv_buf_pool_chunk_unit,
0, 0, SIZE_T_MAX, 1024 * 1024);
static MYSQL_SYSVAR_STR(buffer_pool_filename, srv_buf_dump_filename,
- PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Filename to/from which to dump/load the InnoDB buffer pool",
- innodb_srv_buf_dump_filename_validate, NULL, SRV_BUF_DUMP_FILENAME_DEFAULT);
+ NULL, NULL, SRV_BUF_DUMP_FILENAME_DEFAULT);
static MYSQL_SYSVAR_BOOL(buffer_pool_dump_now, innodb_buffer_pool_dump_now,
PLUGIN_VAR_RQCMDARG,
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index 3b537afef40..3cb51f5e15d 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -4935,10 +4935,10 @@ static ST_FIELD_INFO innodb_sysindex_fields_info[]=
Column("N_FIELDS", SLong(), NOT_NULL),
#define SYS_INDEX_PAGE_NO 5
- Column("PAGE_NO", SLong(), NOT_NULL),
+ Column("PAGE_NO", SLong(), NULLABLE),
#define SYS_INDEX_SPACE 6
- Column("SPACE", SLong(), NOT_NULL),
+ Column("SPACE", SLong(), NULLABLE),
#define SYS_INDEX_MERGE_THRESHOLD 7
Column("MERGE_THRESHOLD", SLong(), NOT_NULL),
@@ -4990,12 +4990,14 @@ i_s_dict_fill_sys_indexes(
if (index->page == FIL_NULL) {
fields[SYS_INDEX_PAGE_NO]->set_null();
} else {
+ fields[SYS_INDEX_PAGE_NO]->set_notnull();
OK(fields[SYS_INDEX_PAGE_NO]->store(index->page, true));
}
- if (space_id == ULINT_UNDEFINED) {
+ if (space_id == FIL_NULL) {
fields[SYS_INDEX_SPACE]->set_null();
} else {
+ fields[SYS_INDEX_SPACE]->set_notnull();
OK(fields[SYS_INDEX_SPACE]->store(space_id, true));
}
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index 74905638698..4295c3ba342 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -1689,8 +1689,6 @@ public:
/** map of block->frame to buf_block_t blocks that belong
to buf_buddy_alloc(); protected by buf_pool.mutex */
hash_table_t zip_hash;
- /** number of pending read operations */
- Atomic_counter<ulint> n_pend_reads;
Atomic_counter<ulint>
n_pend_unzip; /*!< number of pending decompressions */
@@ -1717,7 +1715,7 @@ public:
/** flush_list size in bytes; protected by flush_list_mutex */
ulint flush_list_bytes;
/** possibly modified persistent pages (a subset of LRU);
- buf_dblwr.pending_writes() is approximately COUNT(is_write_fixed()) */
+ os_aio_pending_writes() is approximately COUNT(is_write_fixed()) */
UT_LIST_BASE_NODE_T(buf_page_t) flush_list;
/** number of blocks ever added to flush_list;
sometimes protected by flush_list_mutex */
@@ -1876,18 +1874,6 @@ public:
/** Reserve a buffer. */
buf_tmp_buffer_t *io_buf_reserve() { return io_buf.reserve(); }
- /** @return whether any I/O is pending */
- bool any_io_pending()
- {
- if (n_pend_reads)
- return true;
- mysql_mutex_lock(&flush_list_mutex);
- const bool any_pending= page_cleaner_status > PAGE_CLEANER_IDLE ||
- buf_dblwr.pending_writes();
- mysql_mutex_unlock(&flush_list_mutex);
- return any_pending;
- }
-
/** Remove a block from flush_list.
@param bpage buffer pool page */
void delete_from_flush_list(buf_page_t *bpage) noexcept;
diff --git a/storage/innobase/include/buf0dblwr.h b/storage/innobase/include/buf0dblwr.h
index d9c9239c0b4..92b840d2f4c 100644
--- a/storage/innobase/include/buf0dblwr.h
+++ b/storage/innobase/include/buf0dblwr.h
@@ -72,10 +72,6 @@ class buf_dblwr_t
ulint writes_completed;
/** number of pages written by flush_buffered_writes_completed() */
ulint pages_written;
- /** condition variable for !writes_pending */
- pthread_cond_t write_cond;
- /** number of pending page writes */
- size_t writes_pending;
slot slots[2];
slot *active_slot;
@@ -124,7 +120,7 @@ public:
void recover();
/** Update the doublewrite buffer on data page write completion. */
- void write_completed(bool with_doublewrite);
+ void write_completed();
/** Flush possible buffered writes to persistent storage.
It is very important to call this function after a batch of writes has been
posted, and also when we may have to wait for a page latch!
@@ -167,40 +163,6 @@ public:
my_cond_wait(&cond, &mutex.m_mutex);
mysql_mutex_unlock(&mutex);
}
-
- /** Register an unbuffered page write */
- void add_unbuffered()
- {
- mysql_mutex_lock(&mutex);
- writes_pending++;
- mysql_mutex_unlock(&mutex);
- }
-
- size_t pending_writes()
- {
- mysql_mutex_lock(&mutex);
- const size_t pending{writes_pending};
- mysql_mutex_unlock(&mutex);
- return pending;
- }
-
- /** Wait for writes_pending to reach 0 */
- void wait_for_page_writes()
- {
- mysql_mutex_lock(&mutex);
- while (writes_pending)
- my_cond_wait(&write_cond, &mutex.m_mutex);
- mysql_mutex_unlock(&mutex);
- }
-
- /** Wait for writes_pending to reach 0 */
- void wait_for_page_writes(const timespec &abstime)
- {
- mysql_mutex_lock(&mutex);
- while (writes_pending)
- my_cond_timedwait(&write_cond, &mutex.m_mutex, &abstime);
- mysql_mutex_unlock(&mutex);
- }
};
/** The doublewrite buffer */
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 483d594c6b9..008cb3d1261 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -626,8 +626,7 @@ private:
@return number of pending operations, possibly with NEEDS_FSYNC flag */
uint32_t set_closing()
{
- return n_pending.fetch_or(CLOSING, std::memory_order_acquire) &
- (PENDING | NEEDS_FSYNC);
+ return n_pending.fetch_or(CLOSING, std::memory_order_acquire);
}
public:
diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index da9dec05827..d5239ec3f9a 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -462,5 +462,15 @@ void destroy_background_thd(MYSQL_THD thd);
void
innobase_reset_background_thd(MYSQL_THD);
+#ifdef WITH_WSREP
+/** Append table-level exclusive key.
+@param thd MySQL thread handle
+@param table table
+@retval false on success
+@retval true on failure */
+struct dict_table_t;
+bool wsrep_append_table_key(MYSQL_THD thd, const dict_table_t &table);
+#endif /* WITH_WSREP */
+
#endif /* !UNIV_INNOCHECKSUM */
#endif /* HA_INNODB_PROTOTYPES_H */
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index 09e4ece8894..58a2ee3468c 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/include/log0log.h
@@ -378,7 +378,6 @@ public:
lsn_t get_lsn(std::memory_order order= std::memory_order_relaxed) const
{ return lsn.load(order); }
- void set_lsn(lsn_t lsn) { this->lsn.store(lsn, std::memory_order_release); }
lsn_t get_flushed_lsn(std::memory_order order= std::memory_order_acquire)
const noexcept
diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h
index c0e5f7683a9..764071cfab9 100644
--- a/storage/innobase/include/os0file.h
+++ b/storage/innobase/include/os0file.h
@@ -933,13 +933,14 @@ os_file_flush_func(
/** Retrieves the last error number if an error occurs in a file io function.
The number should be retrieved before any other OS calls (because they may
overwrite the error number). If the number is not known to this program,
-the OS error number + 100 is returned.
-@param[in] report true if we want an error message printed
- for all errors
-@return error number, or OS error number + 100 */
-ulint
-os_file_get_last_error(
- bool report);
+the OS error number + OS_FILE_ERROR_MAX is returned.
+@param[in] report_all_errors true if we want an error message
+ printed of all errors
+@param[in] on_error_silent true then don't print any diagnostic
+ to the log
+@return error number, or OS error number + OS_FILE_ERROR_MAX */
+ulint os_file_get_last_error(bool report_all_errors,
+ bool on_error_silent= false);
/** NOTE! Use the corresponding macro os_file_read(), not directly this
function!
@@ -1048,6 +1049,13 @@ void os_aio_free();
@retval DB_IO_ERROR on I/O error */
dberr_t os_aio(const IORequest &type, void *buf, os_offset_t offset, size_t n);
+/** @return number of pending reads */
+size_t os_aio_pending_reads();
+/** @return approximate number of pending reads */
+size_t os_aio_pending_reads_approx();
+/** @return number of pending writes */
+size_t os_aio_pending_writes();
+
/** Wait until there are no pending asynchronous writes. */
void os_aio_wait_until_no_pending_writes();
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index b85fa518384..0f02e307a47 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -329,6 +329,9 @@ extern my_bool srv_immediate_scrub_data_uncompressed;
enum srv_operation_mode {
/** Normal mode (MariaDB Server) */
SRV_OPERATION_NORMAL,
+ /** Mariabackup is executing server to export already restored
+ tablespaces */
+ SRV_OPERATION_EXPORT_RESTORED,
/** Mariabackup taking a backup */
SRV_OPERATION_BACKUP,
/** Mariabackup restoring a backup for subsequent --copy-back */
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 793f7b327c8..88b6bae963f 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -1205,7 +1205,7 @@ static void fil_name_process(const char *name, ulint len, uint32_t space_id,
return;
}
- ut_ad(srv_operation == SRV_OPERATION_NORMAL
+ ut_ad(srv_operation <= SRV_OPERATION_EXPORT_RESTORED
|| srv_operation == SRV_OPERATION_RESTORE
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT);
@@ -1324,8 +1324,9 @@ same_space:
ut_ad(space == NULL);
if (srv_force_recovery == 0) {
sql_print_error("InnoDB: Recovery cannot access"
- " file %s (tablespace "
- UINT32PF ")", name, space_id);
+ " file %.*s (tablespace "
+ UINT32PF ")", int(len), name,
+ space_id);
sql_print_information("InnoDB: You may set "
"innodb_force_recovery=1"
" to ignore this and"
@@ -1336,9 +1337,10 @@ same_space:
}
sql_print_warning("InnoDB: Ignoring changes to"
- " file %s (tablespace " UINT32PF ")"
+ " file %.*s (tablespace "
+ UINT32PF ")"
" due to innodb_force_recovery",
- name, space_id);
+ int(len), name, space_id);
}
}
}
@@ -3413,7 +3415,7 @@ static void log_sort_flush_list()
@param last_batch whether it is possible to write more redo log */
void recv_sys_t::apply(bool last_batch)
{
- ut_ad(srv_operation == SRV_OPERATION_NORMAL ||
+ ut_ad(srv_operation <= SRV_OPERATION_EXPORT_RESTORED ||
srv_operation == SRV_OPERATION_RESTORE ||
srv_operation == SRV_OPERATION_RESTORE_EXPORT);
@@ -3568,7 +3570,7 @@ next_free_block:
for (;;)
{
const bool empty= pages.empty();
- if (empty && !buf_pool.n_pend_reads)
+ if (empty && !os_aio_pending_reads())
break;
if (!is_corrupt_fs() && !is_corrupt_log())
@@ -3581,7 +3583,6 @@ next_free_block:
{
mysql_mutex_unlock(&mutex);
os_aio_wait_until_no_pending_reads();
- ut_ad(!buf_pool.n_pend_reads);
mysql_mutex_lock(&mutex);
ut_ad(pages.empty());
}
@@ -4139,7 +4140,7 @@ dberr_t recv_recovery_from_checkpoint_start()
{
bool rescan = false;
- ut_ad(srv_operation == SRV_OPERATION_NORMAL
+ ut_ad(srv_operation <= SRV_OPERATION_EXPORT_RESTORED
|| srv_operation == SRV_OPERATION_RESTORE
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT);
ut_d(mysql_mutex_lock(&buf_pool.flush_list_mutex));
@@ -4256,7 +4257,7 @@ read_only_recovery:
rescan = true;
}
- if (srv_operation == SRV_OPERATION_NORMAL) {
+ if (srv_operation <= SRV_OPERATION_EXPORT_RESTORED) {
deferred_spaces.deferred_dblwr();
buf_dblwr.recover();
}
@@ -4319,7 +4320,7 @@ err_exit:
}
log_sys.buf_free = recv_sys.offset;
if (recv_needed_recovery
- && srv_operation == SRV_OPERATION_NORMAL) {
+ && srv_operation <= SRV_OPERATION_EXPORT_RESTORED) {
/* Write a FILE_CHECKPOINT marker as the first thing,
before generating any other redo log. This ensures
that subsequent crash recovery will be possible even
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index c7164ccc3ff..d28d7b02c43 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -124,6 +124,11 @@ public:
{
wait();
}
+
+ mysql_mutex_t& mutex()
+ {
+ return m_cache.mutex();
+ }
};
static io_slots *read_slots;
@@ -727,22 +732,16 @@ os_file_punch_hole_posix(
return(DB_IO_NO_PUNCH_HOLE);
}
-
-
/** Retrieves the last error number if an error occurs in a file io function.
The number should be retrieved before any other OS calls (because they may
overwrite the error number). If the number is not known to this program,
the OS error number + 100 is returned.
@param[in] report_all_errors true if we want an error message
- printed of all errors
+ printed of all errors
@param[in] on_error_silent true then don't print any diagnostic
to the log
@return error number, or OS error number + 100 */
-static
-ulint
-os_file_get_last_error_low(
- bool report_all_errors,
- bool on_error_silent)
+ulint os_file_get_last_error(bool report_all_errors, bool on_error_silent)
{
int err = errno;
@@ -1803,16 +1802,13 @@ bool os_file_flush_func(os_file_t file)
The number should be retrieved before any other OS calls (because they may
overwrite the error number). If the number is not known to this program,
then OS error number + OS_FILE_ERROR_MAX is returned.
-@param[in] report_all_errors true if we want an error message printed
- of all errors
+@param[in] report_all_errors true if we want an error message
+printed of all errors
@param[in] on_error_silent true then don't print any diagnostic
to the log
@return error number, or OS error number + OS_FILE_ERROR_MAX */
-static
-ulint
-os_file_get_last_error_low(
- bool report_all_errors,
- bool on_error_silent)
+ulint os_file_get_last_error(bool report_all_errors, bool on_error_silent)
+
{
ulint err = (ulint) GetLastError();
@@ -2936,20 +2932,6 @@ os_file_read_func(
return err ? err : DB_IO_ERROR;
}
-/** Retrieves the last error number if an error occurs in a file io function.
-The number should be retrieved before any other OS calls (because they may
-overwrite the error number). If the number is not known to this program,
-the OS error number + 100 is returned.
-@param[in] report_all_errors true if we want an error printed
- for all errors
-@return error number, or OS error number + 100 */
-ulint
-os_file_get_last_error(
- bool report_all_errors)
-{
- return(os_file_get_last_error_low(report_all_errors, false));
-}
-
/** Handle errors for file operations.
@param[in] name name of a file or NULL
@param[in] operation operation
@@ -2966,7 +2948,7 @@ os_file_handle_error_cond_exit(
{
ulint err;
- err = os_file_get_last_error_low(false, on_error_silent);
+ err = os_file_get_last_error(false, on_error_silent);
switch (err) {
case OS_FILE_DISK_FULL:
@@ -3663,6 +3645,30 @@ void os_aio_wait_until_no_pending_writes()
buf_dblwr.wait_flush_buffered_writes();
}
+/** @return number of pending reads */
+size_t os_aio_pending_reads()
+{
+ mysql_mutex_lock(&read_slots->mutex());
+ size_t pending= read_slots->pending_io_count();
+ mysql_mutex_unlock(&read_slots->mutex());
+ return pending;
+}
+
+/** @return approximate number of pending reads */
+size_t os_aio_pending_reads_approx()
+{
+ return read_slots->pending_io_count();
+}
+
+/** @return number of pending writes */
+size_t os_aio_pending_writes()
+{
+ mysql_mutex_lock(&write_slots->mutex());
+ size_t pending= write_slots->pending_io_count();
+ mysql_mutex_unlock(&write_slots->mutex());
+ return pending;
+}
+
/** Wait until all pending asynchronous reads have completed. */
void os_aio_wait_until_no_pending_reads()
{
diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc
index ba1bb24b43b..89e6d1497b7 100644
--- a/storage/innobase/page/page0zip.cc
+++ b/storage/innobase/page/page0zip.cc
@@ -3371,7 +3371,7 @@ page_zip_validate_low(
differed. Let us ignore it. */
page_zip_fail(("page_zip_validate:"
" min_rec_flag"
- " (%s" ULINTPF "," ULINTPF
+ " (%s" UINT32PF "," UINT32PF
",0x%02x)\n",
sloppy ? "ignored, " : "",
page_get_space_id(page),
@@ -3416,7 +3416,8 @@ page_zip_validate_low(
page + PAGE_NEW_INFIMUM, TRUE);
trec = page_rec_get_next_low(
temp_page + PAGE_NEW_INFIMUM, TRUE);
- const ulint n_core = page_is_leaf(page) ? index->n_fields : 0;
+ const ulint n_core = (index && page_is_leaf(page))
+ ? index->n_fields : 0;
do {
if (page_offset(rec) != page_offset(trec)) {
diff --git a/storage/innobase/rem/rem0cmp.cc b/storage/innobase/rem/rem0cmp.cc
index c2b2bc7120d..d190a001b6f 100644
--- a/storage/innobase/rem/rem0cmp.cc
+++ b/storage/innobase/rem/rem0cmp.cc
@@ -300,8 +300,9 @@ int cmp_data(ulint mtype, ulint prtype, bool descending,
DBUG_ASSERT(is_strnncoll_compatible(prtype & DATA_MYSQL_TYPE_MASK));
if (CHARSET_INFO *cs= all_charsets[dtype_get_charset_coll(prtype)])
{
- cmp= cs->coll->strnncollsp_nchars(cs, data1, len1, data2, len2,
- std::max(len1, len2));
+ cmp= cs->coll->
+ strnncollsp_nchars(cs, data1, len1, data2, len2, std::max(len1, len2),
+ MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES);
goto func_exit;
}
goto no_collation;
diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc
index 98cf2dda900..d743ef9aa5c 100644
--- a/storage/innobase/rem/rem0rec.cc
+++ b/storage/innobase/rem/rem0rec.cc
@@ -291,7 +291,9 @@ rec_init_offsets_comp_ordinary(
!= n_core)
? UT_BITS_IN_BYTES(unsigned(index->get_n_nullable(n_core)))
: (redundant_temp
- ? UT_BITS_IN_BYTES(index->n_nullable)
+ ? (index->is_instant()
+ ? UT_BITS_IN_BYTES(index->get_n_nullable(n_core))
+ : UT_BITS_IN_BYTES(index->n_nullable))
: index->n_core_null_bytes);
if (mblob) {
@@ -448,7 +450,7 @@ start:
continue;
}
- len = offs += len;
+ len = offs += static_cast<rec_offs>(len);
} else {
len = offs += field->fixed_len;
}
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
index 2dcc16130c3..8b35728f35b 100644
--- a/storage/innobase/row/row0import.cc
+++ b/storage/innobase/row/row0import.cc
@@ -3883,6 +3883,7 @@ page_corrupted:
block->page.zip.data = src;
frame_changed = true;
} else if (!page_compressed
+ && type != FIL_PAGE_TYPE_XDES
&& !block->page.zip.data) {
block->page.frame = src;
frame_changed = true;
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index e327717ce65..463fb90d714 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -49,6 +49,7 @@ Created 4/20/1996 Heikki Tuuri
#ifdef WITH_WSREP
#include <wsrep.h>
#include <mysql/service_wsrep.h>
+#include "ha_prototypes.h"
#endif /* WITH_WSREP */
/*************************************************************************
@@ -2578,42 +2579,6 @@ but GCC 4.8.5 does not support pop_options. */
# pragma GCC optimize ("O0")
#endif
-#ifdef WITH_WSREP
-/** Start bulk insert operation for Galera by appending
-table-level exclusive key for bulk insert.
-@param trx transaction
-@param index index
-@retval false on success
-@retval true on failure */
-ATTRIBUTE_COLD static bool row_ins_wsrep_start_bulk(trx_t *trx, const dict_index_t &index)
-{
- char db_buf[NAME_LEN + 1];
- char tbl_buf[NAME_LEN + 1];
- ulint db_buf_len, tbl_buf_len;
-
- if (!index.table->parse_name(db_buf, tbl_buf, &db_buf_len, &tbl_buf_len))
- {
- WSREP_ERROR("Parse_name for bulk insert failed: %s",
- wsrep_thd_query(trx->mysql_thd));
- trx->error_state = DB_ROLLBACK;
- return true;
- }
-
- /* Append table-level exclusive key for bulk insert. */
- const int rcode = wsrep_thd_append_table_key(trx->mysql_thd, db_buf,
- tbl_buf, WSREP_SERVICE_KEY_EXCLUSIVE);
- if (rcode)
- {
- WSREP_ERROR("Appending table key for bulk insert failed: %s, %d",
- wsrep_thd_query(trx->mysql_thd), rcode);
- trx->error_state = DB_ROLLBACK;
- return true;
- }
-
- return false;
-}
-#endif
-
/***************************************************************//**
Tries to insert an entry into a clustered index, ignoring foreign key
constraints. If a record with the same unique key is found, the other
@@ -2780,10 +2745,13 @@ avoid_bulk:
#ifdef WITH_WSREP
if (trx->is_wsrep())
{
- if (!wsrep_thd_is_local_transaction(trx->mysql_thd))
- goto skip_bulk_insert;
- if (row_ins_wsrep_start_bulk(trx, *index))
- goto err_exit;
+ if (!wsrep_thd_is_local_transaction(trx->mysql_thd))
+ goto skip_bulk_insert;
+ if (wsrep_append_table_key(trx->mysql_thd, *index->table))
+ {
+ trx->error_state = DB_ROLLBACK;
+ goto err_exit;
+ }
}
#endif /* WITH_WSREP */
diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc
index a4b52fd2a2f..9b11b7fbc3f 100644
--- a/storage/innobase/row/row0vers.cc
+++ b/storage/innobase/row/row0vers.cc
@@ -859,6 +859,30 @@ static bool dtuple_coll_eq(const dtuple_t &tuple1, const dtuple_t &tuple2)
return true;
}
+/** Find out whether data tuple has missing data type
+for indexed virtual column.
+@param tuple data tuple
+@param index virtual index
+@return true if tuple has missing column type */
+static bool dtuple_vcol_data_missing(const dtuple_t &tuple,
+ dict_index_t *index)
+{
+ for (ulint i= 0; i < index->n_uniq; i++)
+ {
+ dict_col_t *col= index->fields[i].col;
+ if (!col->is_virtual())
+ continue;
+ dict_v_col_t *vcol= reinterpret_cast<dict_v_col_t*>(col);
+ for (ulint j= 0; j < index->table->n_v_cols; j++)
+ {
+ if (vcol == &index->table->v_cols[j]
+ && tuple.v_fields[j].type.mtype == DATA_MISSING)
+ return true;
+ }
+ }
+ return false;
+}
+
/** Finds out if a version of the record, where the version >= the current
purge_sys.view, should have ientry as its secondary index entry. We check
if there is any not delete marked version of the record where the trx
@@ -1068,6 +1092,9 @@ unsafe_to_purge:
if (dict_index_has_virtual(index)) {
if (vrow) {
+ if (dtuple_vcol_data_missing(*vrow, index)) {
+ goto nochange_index;
+ }
/* Keep the virtual row info for the next
version, unless it is changed */
mem_heap_empty(v_heap);
@@ -1078,6 +1105,7 @@ unsafe_to_purge:
if (!cur_vrow) {
/* Nothing for this index has changed,
continue */
+nochange_index:
version = prev_version;
continue;
}
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 5d08c18a8e5..017a7b8d08a 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -189,7 +189,11 @@ static dberr_t create_log_file(bool create_new_db, lsn_t lsn)
ib_logfile0 in log_t::rename_resized(). */
delete_log_files();
- DBUG_ASSERT(!buf_pool.any_io_pending());
+ ut_ad(!os_aio_pending_reads());
+ ut_ad(!os_aio_pending_writes());
+ ut_d(mysql_mutex_lock(&buf_pool.flush_list_mutex));
+ ut_ad(!buf_pool.get_oldest_modification(0));
+ ut_d(mysql_mutex_unlock(&buf_pool.flush_list_mutex));
log_sys.latch.wr_lock(SRW_LOCK_CALL);
log_sys.set_capacity();
@@ -598,7 +602,7 @@ dberr_t srv_undo_tablespaces_init(bool create_new_db)
srv_undo_tablespaces_open= 0;
ut_a(srv_undo_tablespaces <= TRX_SYS_N_RSEGS);
- ut_a(!create_new_db || srv_operation == SRV_OPERATION_NORMAL);
+ ut_a(!create_new_db || srv_operation <= SRV_OPERATION_EXPORT_RESTORED);
if (srv_undo_tablespaces == 1)
srv_undo_tablespaces= 0;
@@ -857,7 +861,11 @@ same_size:
log_write_up_to(flushed_lsn, false);
ut_ad(flushed_lsn == log_sys.get_lsn());
- ut_ad(!buf_pool.any_io_pending());
+ ut_ad(!os_aio_pending_reads());
+ ut_ad(!os_aio_pending_writes());
+ ut_d(mysql_mutex_lock(&buf_pool.flush_list_mutex));
+ ut_ad(!buf_pool.get_oldest_modification(0));
+ ut_d(mysql_mutex_unlock(&buf_pool.flush_list_mutex));
DBUG_RETURN(flushed_lsn);
}
@@ -875,7 +883,7 @@ dberr_t srv_start(bool create_new_db)
dberr_t err = DB_SUCCESS;
mtr_t mtr;
- ut_ad(srv_operation == SRV_OPERATION_NORMAL
+ ut_ad(srv_operation <= SRV_OPERATION_RESTORE_EXPORT
|| srv_operation == SRV_OPERATION_RESTORE
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT);
@@ -1204,7 +1212,8 @@ dberr_t srv_start(bool create_new_db)
}
switch (srv_operation) {
- case SRV_OPERATION_NORMAL:
+ case SRV_OPERATION_NORMAL:
+ case SRV_OPERATION_EXPORT_RESTORED:
case SRV_OPERATION_RESTORE_EXPORT:
/* Initialize the change buffer. */
err = dict_boot();
@@ -1342,7 +1351,7 @@ dberr_t srv_start(bool create_new_db)
}
}
- if (srv_operation != SRV_OPERATION_NORMAL) {
+ if (srv_operation > SRV_OPERATION_EXPORT_RESTORED) {
ut_ad(srv_operation == SRV_OPERATION_RESTORE_EXPORT
|| srv_operation == SRV_OPERATION_RESTORE);
return(err);
@@ -1374,7 +1383,11 @@ dberr_t srv_start(bool create_new_db)
threads until creating a log checkpoint at the
end of create_log_file(). */
ut_d(recv_no_log_write = true);
- DBUG_ASSERT(!buf_pool.any_io_pending());
+ ut_ad(!os_aio_pending_reads());
+ ut_ad(!os_aio_pending_writes());
+ ut_d(mysql_mutex_lock(&buf_pool.flush_list_mutex));
+ ut_ad(!buf_pool.get_oldest_modification(0));
+ ut_d(mysql_mutex_unlock(&buf_pool.flush_list_mutex));
/* Close the redo log file, so that we can replace it */
log_sys.close_file();
@@ -1559,7 +1572,8 @@ skip_monitors:
return(srv_init_abort(err));
}
- if (!srv_read_only_mode && srv_operation == SRV_OPERATION_NORMAL) {
+ if (!srv_read_only_mode
+ && srv_operation <= SRV_OPERATION_EXPORT_RESTORED) {
/* Initialize the innodb_temporary tablespace and keep
it open until shutdown. */
err = srv_open_tmp_tablespace(create_new_db);
@@ -1649,7 +1663,7 @@ void innodb_preshutdown()
if (srv_read_only_mode)
return;
- if (!srv_fast_shutdown && srv_operation == SRV_OPERATION_NORMAL)
+ if (!srv_fast_shutdown && srv_operation <= SRV_OPERATION_EXPORT_RESTORED)
{
/* Because a slow shutdown must empty the change buffer, we had
better prevent any further changes from being buffered. */
@@ -1689,6 +1703,7 @@ void innodb_shutdown()
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
break;
case SRV_OPERATION_NORMAL:
+ case SRV_OPERATION_EXPORT_RESTORED:
/* Shut down the persistent files. */
logs_empty_and_mark_files_at_shutdown();
}