Commit 6010a27c authored by Sergei Golubchik's avatar Sergei Golubchik

5.5.52-38.3

parent e316c46f
......@@ -76,7 +76,7 @@ btr_corruption_report(
buf_block_get_zip_size(block),
BUF_PAGE_PRINT_NO_CRASH);
}
buf_page_print(buf_block_get_frame(block), 0, 0);
buf_page_print(buf_nonnull_block_get_frame(block), 0, 0);
}
#ifndef UNIV_HOTBACKUP
......@@ -1077,7 +1077,7 @@ btr_get_size(
SRV_CORRUPT_TABLE_CHECK(root,
{
mtr_commit(mtr);
return(0);
return(ULINT_UNDEFINED);
});
if (flag == BTR_N_LEAF_PAGES) {
......
......@@ -475,6 +475,19 @@ innobase_is_fake_change(
THD* thd); /*!< in: MySQL thread handle of the user for
whom the transaction is being committed */
/** Get the list of foreign keys referencing a specified table
table.
@param thd The thread handle
@param path Path to the table
@param f_key_list[out] The list of foreign keys
@return error code or zero for success */
static
int
innobase_get_parent_fk_list(
THD* thd,
const char* path,
List<FOREIGN_KEY_INFO>* f_key_list);
/******************************************************************//**
Maps a MySQL trx isolation level code to the InnoDB isolation level code
......@@ -2710,6 +2723,7 @@ innobase_init(
innobase_hton->purge_changed_page_bitmaps
= innobase_purge_changed_page_bitmaps;
innobase_hton->is_fake_change = innobase_is_fake_change;
innobase_hton->get_parent_fk_list = innobase_get_parent_fk_list;
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
......@@ -9721,7 +9735,14 @@ ha_innobase::check(
prebuilt->select_lock_type = LOCK_NONE;
if (!row_check_index_for_mysql(prebuilt, index, &n_rows)) {
bool check_result
= row_check_index_for_mysql(prebuilt, index, &n_rows);
DBUG_EXECUTE_IF(
"dict_set_index_corrupted",
if (!(index->type & DICT_CLUSTERED)) {
check_result = false;
});
if (!check_result) {
innobase_format_name(
index_name, sizeof index_name,
index->name, TRUE);
......@@ -10057,6 +10078,73 @@ get_foreign_key_info(
return(pf_key_info);
}
/** Get the list of foreign keys referencing a specified table
table.
@param thd The thread handle
@param path Path to the table
@param f_key_list[out] The list of foreign keys */
static
void
fill_foreign_key_list(THD* thd,
const dict_table_t* table,
List<FOREIGN_KEY_INFO>* f_key_list)
{
ut_ad(mutex_own(&dict_sys->mutex));
for (dict_foreign_t* foreign
= UT_LIST_GET_FIRST(table->referenced_list);
foreign != NULL;
foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
FOREIGN_KEY_INFO* pf_key_info
= get_foreign_key_info(thd, foreign);
if (pf_key_info) {
f_key_list->push_back(pf_key_info);
}
}
}
/** Get the list of foreign keys referencing a specified table
table.
@param thd The thread handle
@param path Path to the table
@param f_key_list[out] The list of foreign keys
@return error code or zero for success */
static
int
innobase_get_parent_fk_list(
THD* thd,
const char* path,
List<FOREIGN_KEY_INFO>* f_key_list)
{
ut_a(strlen(path) <= FN_REFLEN);
char norm_name[FN_REFLEN + 1];
normalize_table_name(norm_name, path);
trx_t* parent_trx = check_trx_exists(thd);
parent_trx->op_info = "getting list of referencing foreign keys";
trx_search_latch_release_if_reserved(parent_trx);
mutex_enter(&dict_sys->mutex);
dict_table_t* table
= dict_table_get_low(norm_name,
static_cast<dict_err_ignore_t>(
DICT_ERR_IGNORE_INDEX_ROOT
| DICT_ERR_IGNORE_CORRUPT));
if (!table) {
mutex_exit(&dict_sys->mutex);
return(HA_ERR_NO_SUCH_TABLE);
}
fill_foreign_key_list(thd, table, f_key_list);
mutex_exit(&dict_sys->mutex);
parent_trx->op_info = "";
return(0);
}
/*******************************************************************//**
Gets the list of foreign keys in this table.
@return always 0, that is, always succeeds */
......@@ -10105,9 +10193,6 @@ ha_innobase::get_parent_foreign_key_list(
THD* thd, /*!< in: user thread handle */
List<FOREIGN_KEY_INFO>* f_key_list) /*!< out: foreign key list */
{
FOREIGN_KEY_INFO* pf_key_info;
dict_foreign_t* foreign;
ut_a(prebuilt != NULL);
update_thd(ha_thd());
......@@ -10116,16 +10201,7 @@ ha_innobase::get_parent_foreign_key_list(
trx_search_latch_release_if_reserved(prebuilt->trx);
mutex_enter(&(dict_sys->mutex));
for (foreign = UT_LIST_GET_FIRST(prebuilt->table->referenced_list);
foreign != NULL;
foreign = UT_LIST_GET_NEXT(referenced_list, foreign)) {
pf_key_info = get_foreign_key_info(thd, foreign);
if (pf_key_info) {
f_key_list->push_back(pf_key_info);
}
}
fill_foreign_key_list(thd, prebuilt->table, f_key_list);
mutex_exit(&(dict_sys->mutex));
prebuilt->trx->op_info = "";
......@@ -12539,7 +12615,6 @@ innodb_track_changed_pages_validate(
for update function */
struct st_mysql_value* value) /*!< in: incoming bool */
{
static bool enabled_on_startup = false;
long long intbuf = 0;
if (value->val_int(value, &intbuf)) {
......@@ -12547,8 +12622,7 @@ innodb_track_changed_pages_validate(
return 1;
}
if (srv_track_changed_pages || enabled_on_startup) {
enabled_on_startup = true;
if (srv_redo_log_thread_started) {
*reinterpret_cast<ulong*>(save)
= static_cast<ulong>(intbuf);
return 0;
......
......@@ -1110,8 +1110,20 @@ buf_block_get_frame(
/*================*/
const buf_block_t* block) /*!< in: pointer to the control block */
__attribute__((pure));
/*********************************************************************//**
Gets a pointer to the memory frame of a block, where block is known not to be
NULL.
@return pointer to the frame */
UNIV_INLINE
buf_frame_t*
buf_nonnull_block_get_frame(
const buf_block_t* block) /*!< in: pointer to the control block */
__attribute__((pure));
#else /* UNIV_DEBUG */
# define buf_block_get_frame(block) (block ? (block)->frame : 0)
# define buf_nonnull_block_get_frame(block) ((block)->frame)
#endif /* UNIV_DEBUG */
/*********************************************************************//**
Gets the space id of a block.
......
......@@ -718,6 +718,19 @@ buf_block_get_frame(
{
SRV_CORRUPT_TABLE_CHECK(block, return(0););
return(buf_nonnull_block_get_frame(block));
}
/*********************************************************************//**
Gets a pointer to the memory frame of a block, where block is known not to be
NULL.
@return pointer to the frame */
UNIV_INLINE
buf_frame_t*
buf_nonnull_block_get_frame(
/*========================*/
const buf_block_t* block) /*!< in: pointer to the control block */
{
switch (buf_block_get_state(block)) {
case BUF_BLOCK_ZIP_FREE:
case BUF_BLOCK_ZIP_PAGE:
......@@ -739,6 +752,7 @@ buf_block_get_frame(
ok:
return((buf_frame_t*) block->frame);
}
#endif /* UNIV_DEBUG */
/*********************************************************************//**
......
......@@ -74,6 +74,11 @@ extern os_event_t srv_checkpoint_completed_event;
that the (slow) shutdown may proceed */
extern os_event_t srv_redo_log_thread_finished_event;
/** Whether the redo log tracker thread has been started. Does not take into
account whether the tracking is currently enabled (see srv_track_changed_pages
for that) */
extern my_bool srv_redo_log_thread_started;
/* If the last data file is auto-extended, we add this many pages to it
at a time */
#define SRV_AUTO_EXTEND_INCREMENT \
......@@ -141,6 +146,9 @@ extern char* srv_doublewrite_file;
extern ibool srv_recovery_stats;
/** Whether the redo log tracking is currently enabled. Note that it is
possible for the log tracker thread to be running and the tracking to be
disabled */
extern my_bool srv_track_changed_pages;
extern ib_uint64_t srv_max_bitmap_file_size;
......
......@@ -64,7 +64,7 @@ component, i.e. we show M.N.P as M.N */
(INNODB_VERSION_MAJOR << 8 | INNODB_VERSION_MINOR)
#ifndef PERCONA_INNODB_VERSION
#define PERCONA_INNODB_VERSION 38.0
#define PERCONA_INNODB_VERSION 38.3
#endif
#define INNODB_VERSION_STR MYSQL_SERVER_VERSION
......
......@@ -3326,6 +3326,8 @@ logs_empty_and_mark_files_at_shutdown(void)
algorithm only works if the server is idle at shutdown */
srv_shutdown_state = SRV_SHUTDOWN_CLEANUP;
srv_wake_purge_thread();
loop:
os_thread_sleep(100000);
......@@ -3499,7 +3501,7 @@ logs_empty_and_mark_files_at_shutdown(void)
srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
/* Wake the log tracking thread which will then immediatelly
quit because of srv_shutdown_state value */
if (srv_track_changed_pages) {
if (srv_redo_log_thread_started) {
os_event_set(srv_checkpoint_completed_event);
os_event_wait(srv_redo_log_thread_finished_event);
}
......@@ -3576,7 +3578,7 @@ logs_empty_and_mark_files_at_shutdown(void)
srv_shutdown_state = SRV_SHUTDOWN_LAST_PHASE;
/* Signal the log following thread to quit */
if (srv_track_changed_pages) {
if (srv_redo_log_thread_started) {
os_event_set(srv_checkpoint_completed_event);
}
......@@ -3600,7 +3602,7 @@ logs_empty_and_mark_files_at_shutdown(void)
fil_flush_file_spaces(FIL_TABLESPACE);
if (srv_track_changed_pages) {
if (srv_redo_log_thread_started) {
os_event_wait(srv_redo_log_thread_finished_event);
}
......
......@@ -1813,7 +1813,7 @@ log_online_purge_changed_page_bitmaps(
lsn = IB_ULONGLONG_MAX;
}
if (srv_track_changed_pages) {
if (srv_redo_log_thread_started) {
/* User requests might happen with both enabled and disabled
tracking */
mutex_enter(&log_bmp_sys->mutex);
......@@ -1821,13 +1821,13 @@ log_online_purge_changed_page_bitmaps(
if (!log_online_setup_bitmap_file_range(&bitmap_files, 0,
IB_ULONGLONG_MAX)) {
if (srv_track_changed_pages) {
if (srv_redo_log_thread_started) {
mutex_exit(&log_bmp_sys->mutex);
}
return TRUE;
}
if (srv_track_changed_pages && lsn > log_bmp_sys->end_lsn) {
if (srv_redo_log_thread_started && lsn > log_bmp_sys->end_lsn) {
/* If we have to delete the current output file, close it
first. */
os_file_close(log_bmp_sys->out.file);
......@@ -1858,7 +1858,7 @@ log_online_purge_changed_page_bitmaps(
}
}
if (srv_track_changed_pages) {
if (srv_redo_log_thread_started) {
if (lsn > log_bmp_sys->end_lsn) {
ib_uint64_t new_file_lsn;
if (lsn == IB_ULONGLONG_MAX) {
......@@ -1869,9 +1869,7 @@ log_online_purge_changed_page_bitmaps(
new_file_lsn = log_bmp_sys->end_lsn;
}
if (!log_online_rotate_bitmap_file(new_file_lsn)) {
/* If file create failed, signal the log
tracking thread to quit next time it wakes
up. */
/* If file create failed, stop log tracking */
srv_track_changed_pages = FALSE;
}
}
......
......@@ -3015,7 +3015,7 @@ recv_recovery_from_checkpoint_start_func(
ib_uint64_t checkpoint_lsn;
ib_uint64_t checkpoint_no;
ib_uint64_t old_scanned_lsn;
ib_uint64_t group_scanned_lsn;
ib_uint64_t group_scanned_lsn = 0;
ib_uint64_t contiguous_lsn;
#ifdef UNIV_LOG_ARCHIVE
ib_uint64_t archived_lsn;
......
......@@ -56,7 +56,18 @@ mach_parse_compressed(
*val = flag;
return(ptr + 1);
} else if (flag < 0xC0UL) {
}
/* Workaround GCC bug
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77673:
the compiler moves mach_read_from_4 right to the beginning of the
function, causing and out-of-bounds read if we are reading a short
integer close to the end of buffer. */
#if defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__clang__)
asm volatile("": : :"memory");
#endif
if (flag < 0xC0UL) {
if (end_ptr < ptr + 2) {
return(NULL);
}
......
......@@ -179,6 +179,9 @@ UNIV_INTERN char* srv_doublewrite_file = NULL;
UNIV_INTERN ibool srv_recovery_stats = FALSE;
/** Whether the redo log tracking is currently enabled. Note that it is
possible for the log tracker thread to be running and the tracking to be
disabled */
UNIV_INTERN my_bool srv_track_changed_pages = FALSE;
UNIV_INTERN ib_uint64_t srv_max_bitmap_file_size = 100 * 1024 * 1024;
......@@ -809,6 +812,11 @@ UNIV_INTERN os_event_t srv_checkpoint_completed_event;
UNIV_INTERN os_event_t srv_redo_log_thread_finished_event;
/** Whether the redo log tracker thread has been started. Does not take into
account whether the tracking is currently enabled (see srv_track_changed_pages
for that) */
UNIV_INTERN my_bool srv_redo_log_thread_started = FALSE;
UNIV_INTERN srv_sys_t* srv_sys = NULL;
/* padding to prevent other memory update hotspots from residing on
......@@ -3179,18 +3187,15 @@ srv_redo_log_follow_thread(
#endif
my_thread_init();
srv_redo_log_thread_started = TRUE;
do {
os_event_wait(srv_checkpoint_completed_event);
os_event_reset(srv_checkpoint_completed_event);
#ifdef UNIV_DEBUG
if (!srv_track_changed_pages) {
continue;
}
#endif
if (srv_track_changed_pages
&& srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE) {
if (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE) {
if (!log_online_follow_redo_log()) {
/* TODO: sync with I_S log tracking status? */
fprintf(stderr,
......@@ -3206,6 +3211,7 @@ srv_redo_log_follow_thread(
srv_track_changed_pages = FALSE;
log_online_read_shutdown();
os_event_set(srv_redo_log_thread_finished_event);
srv_redo_log_thread_started = FALSE; /* Defensive, not required */
my_thread_end();
os_thread_exit(NULL);
......@@ -3327,7 +3333,7 @@ srv_master_do_purge(void)
ut_ad(!mutex_own(&kernel_mutex));
ut_a(srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0));
ut_a(srv_n_purge_threads == 0);
do {
/* Check for shutdown and change in purge config. */
......@@ -3848,7 +3854,7 @@ srv_master_thread(
/* Flush logs if needed */
srv_sync_log_buffer_in_background();
if (srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0)) {
if (srv_n_purge_threads == 0) {
srv_main_thread_op_info = "master purging";
srv_master_do_purge();
......@@ -3926,7 +3932,7 @@ srv_master_thread(
}
}
if (srv_n_purge_threads == 0 || (srv_shutdown_state > 0 && srv_n_threads_active[SRV_WORKER] == 0)) {
if (srv_n_purge_threads == 0) {
srv_main_thread_op_info = "master purging";
srv_master_do_purge();
......@@ -4142,9 +4148,10 @@ srv_purge_thread(
We peek at the history len without holding any mutex
because in the worst case we will end up waiting for
the next purge event. */
if (trx_sys->rseg_history_len < srv_purge_batch_size
|| (n_total_purged == 0
&& retries >= TRX_SYS_N_RSEGS)) {
if (srv_shutdown_state == SRV_SHUTDOWN_NONE
&& (trx_sys->rseg_history_len < srv_purge_batch_size
|| (n_total_purged == 0
&& retries >= TRX_SYS_N_RSEGS))) {
mutex_enter(&kernel_mutex);
......@@ -4159,8 +4166,12 @@ srv_purge_thread(
/* Check for shutdown and whether we should do purge at all. */
if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND
|| srv_shutdown_state != 0
|| srv_fast_shutdown) {
|| (srv_shutdown_state != SRV_SHUTDOWN_NONE
&& srv_fast_shutdown)
|| (srv_shutdown_state != SRV_SHUTDOWN_NONE
&& srv_fast_shutdown == 0
&& n_total_purged == 0
&& retries >= TRX_SYS_N_RSEGS)) {
break;
}
......@@ -4183,6 +4194,9 @@ srv_purge_thread(
srv_sync_log_buffer_in_background();
if (srv_shutdown_state != SRV_SHUTDOWN_NONE)
continue;
cur_time = ut_time_ms();
if (next_itr_time > cur_time) {
os_thread_sleep(ut_min(1000000,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment