1/*****************************************************************************
2
3Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2008, 2009 Google Inc.
5Copyright (c) 2009, Percona Inc.
6Copyright (c) 2013, 2018, MariaDB Corporation.
7
8Portions of this file contain modifications contributed and copyrighted by
9Google, Inc. Those modifications are gratefully acknowledged and are described
10briefly in the InnoDB documentation. The contributions by Google are
11incorporated with their permission, and subject to the conditions contained in
12the file COPYING.Google.
13
14Portions of this file contain modifications contributed and copyrighted
15by Percona Inc.. Those modifications are
16gratefully acknowledged and are described briefly in the InnoDB
17documentation. The contributions by Percona Inc. are incorporated with
18their permission, and subject to the conditions contained in the file
19COPYING.Percona.
20
21This program is free software; you can redistribute it and/or modify it under
22the terms of the GNU General Public License as published by the Free Software
23Foundation; version 2 of the License.
24
25This program is distributed in the hope that it will be useful, but WITHOUT
26ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
28
29You should have received a copy of the GNU General Public License along with
30this program; if not, write to the Free Software Foundation, Inc.,
3151 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
32
33*****************************************************************************/
34
35/**************************************************//**
36@file srv/srv0srv.cc
37The database server main program
38
39Created 10/8/1995 Heikki Tuuri
40*******************************************************/
41
42#include "my_global.h"
43// JAN: TODO: MySQL 5.7 missing header
44//#include "my_thread.h"
45//
46// #include "mysql/psi/mysql_stage.h"
47// #include "mysql/psi/psi.h"
48
49#include "ha_prototypes.h"
50
51#include "btr0sea.h"
52#include "buf0flu.h"
53#include "buf0lru.h"
54#include "dict0boot.h"
55#include "dict0load.h"
56#include "fsp0sysspace.h"
57#include "ibuf0ibuf.h"
58#include "lock0lock.h"
59#include "log0recv.h"
60#include "mem0mem.h"
61#include "os0proc.h"
62#include "pars0pars.h"
63#include "que0que.h"
64#include "row0mysql.h"
65#include "row0trunc.h"
66#include "row0log.h"
67#include "srv0mon.h"
68#include "srv0srv.h"
69#include "srv0start.h"
70#include "sync0sync.h"
71#include "trx0i_s.h"
72#include "trx0purge.h"
73#include "ut0crc32.h"
74#include "btr0defragment.h"
75#include "ut0mem.h"
76#include "fil0fil.h"
77#include "fil0crypt.h"
78#include "fil0pagecompress.h"
79#include "btr0scrub.h"
80
81#include <my_service_manager.h>
82
83#ifdef WITH_WSREP
84extern int wsrep_debug;
85extern int wsrep_trx_is_aborting(void *thd_ptr);
86#endif
87/* The following is the maximum allowed duration of a lock wait. */
88UNIV_INTERN ulong srv_fatal_semaphore_wait_threshold = DEFAULT_SRV_FATAL_SEMAPHORE_TIMEOUT;
89
90/* How much data manipulation language (DML) statements need to be delayed,
91in microseconds, in order to reduce the lagging of the purge thread. */
92ulint srv_dml_needed_delay;
93
94bool srv_monitor_active;
95bool srv_error_monitor_active;
96bool srv_buf_dump_thread_active;
97bool srv_dict_stats_thread_active;
98bool srv_buf_resize_thread_active;
99
100my_bool srv_scrub_log;
101
102const char* srv_main_thread_op_info = "";
103
104/** Prefix used by MySQL to indicate pre-5.1 table name encoding */
105const char srv_mysql50_table_name_prefix[10] = "#mysql50#";
106
107/* Server parameters which are read from the initfile */
108
109/* The following three are dir paths which are catenated before file
110names, where the file name itself may also contain a path */
111
112char* srv_data_home;
113
114/** Rollback files directory, can be absolute. */
115char* srv_undo_dir;
116
117/** The number of tablespaces to use for rollback segments. */
118ulong srv_undo_tablespaces;
119
120/** The number of UNDO tablespaces that are open and ready to use. */
121ulint srv_undo_tablespaces_open;
122
123/** The number of UNDO tablespaces that are active (hosting some rollback
124segment). It is quite possible that some of the tablespaces doesn't host
125any of the rollback-segment based on configuration used. */
126ulint srv_undo_tablespaces_active;
127
128/* The number of rollback segments to use */
129ulong srv_undo_logs;
130
131/** Rate at which UNDO records should be purged. */
132ulong srv_purge_rseg_truncate_frequency;
133
134/** Enable or Disable Truncate of UNDO tablespace.
135Note: If enabled then UNDO tablespace will be selected for truncate.
136While Server waits for undo-tablespace to truncate if user disables
137it, truncate action is completed but no new tablespace is marked
138for truncate (action is never aborted). */
139my_bool srv_undo_log_truncate;
140
141/** Maximum size of undo tablespace. */
142unsigned long long srv_max_undo_log_size;
143
144/** Default undo tablespace size in UNIV_PAGEs count (10MB). */
145const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES =
146 ((1024 * 1024) * 10) / UNIV_PAGE_SIZE_DEF;
147
148/** Set if InnoDB must operate in read-only mode. We don't do any
149recovery and open all tables in RO mode instead of RW mode. We don't
150sync the max trx id to disk either. */
151my_bool srv_read_only_mode;
152/** store to its own file each table created by an user; data
153dictionary tables are in the system tablespace 0 */
154my_bool srv_file_per_table;
155/** Set if InnoDB operates in read-only mode or innodb-force-recovery
156is greater than SRV_FORCE_NO_TRX_UNDO. */
157my_bool high_level_read_only;
158
159/** Place locks to records only i.e. do not use next-key locking except
160on duplicate key checking and foreign key checking */
161ibool srv_locks_unsafe_for_binlog;
162/** Sort buffer size in index creation */
163ulong srv_sort_buf_size;
164/** Maximum modification log file size for online index creation */
165unsigned long long srv_online_max_size;
166
167/* If this flag is TRUE, then we will use the native aio of the
168OS (provided we compiled Innobase with it in), otherwise we will
169use simulated aio we build below with threads.
170Currently we support native aio on windows and linux */
171my_bool srv_use_native_aio;
172my_bool srv_numa_interleave;
173/** copy of innodb_use_atomic_writes; @see innodb_init_params() */
174my_bool srv_use_atomic_writes;
175/** innodb_compression_algorithm; used with page compression */
176ulong innodb_compression_algorithm;
177
178#ifdef UNIV_DEBUG
179/** Used by SET GLOBAL innodb_master_thread_disabled_debug = X. */
180my_bool srv_master_thread_disabled_debug;
181/** Event used to inform that master thread is disabled. */
182static os_event_t srv_master_thread_disabled_event;
183#endif /* UNIV_DEBUG */
184
185/*------------------------- LOG FILES ------------------------ */
186char* srv_log_group_home_dir;
187
188ulong srv_n_log_files;
189/** The InnoDB redo log file size, or 0 when changing the redo log format
190at startup (while disallowing writes to the redo log). */
191ulonglong srv_log_file_size;
192/** innodb_log_buffer_size, in bytes */
193ulong srv_log_buffer_size;
194/** innodb_flush_log_at_trx_commit */
195ulong srv_flush_log_at_trx_commit;
196/** innodb_flush_log_at_timeout */
197uint srv_flush_log_at_timeout;
198/** innodb_page_size */
199ulong srv_page_size;
200/** log2 of innodb_page_size; @see innodb_init_params() */
201ulong srv_page_size_shift;
202/** innodb_log_write_ahead_size */
203ulong srv_log_write_ahead_size;
204
205page_size_t univ_page_size(0, 0, false);
206
207/** innodb_adaptive_flushing; try to flush dirty pages so as to avoid
208IO bursts at the checkpoints. */
209my_bool srv_adaptive_flushing;
210
211/** innodb_flush_sync; whether to ignore io_capacity at log checkpoints */
212my_bool srv_flush_sync;
213
214/** Maximum number of times allowed to conditionally acquire
215mutex before switching to blocking wait on the mutex */
216#define MAX_MUTEX_NOWAIT 20
217
218/** Check whether the number of failed nonblocking mutex
219acquisition attempts exceeds maximum allowed value. If so,
220srv_printf_innodb_monitor() will request mutex acquisition
221with mutex_enter(), which will wait until it gets the mutex. */
222#define MUTEX_NOWAIT(mutex_skipped) ((mutex_skipped) < MAX_MUTEX_NOWAIT)
223
224#ifdef WITH_INNODB_DISALLOW_WRITES
225UNIV_INTERN os_event_t srv_allow_writes_event;
226#endif /* WITH_INNODB_DISALLOW_WRITES */
227
228/** copy of innodb_buffer_pool_size */
229ulint srv_buf_pool_size;
230const ulint srv_buf_pool_min_size = 5 * 1024 * 1024;
231/** Default pool size in bytes */
232const ulint srv_buf_pool_def_size = 128 * 1024 * 1024;
233/** Requested buffer pool chunk size. Each buffer pool instance consists
234of one or more chunks. */
235ulong srv_buf_pool_chunk_unit;
236/** innodb_buffer_pool_instances (0 is interpreted as 1) */
237ulong srv_buf_pool_instances;
238/** Default value of innodb_buffer_pool_instances */
239const ulong srv_buf_pool_instances_default = 0;
240/** innodb_page_hash_locks (a debug-only parameter);
241number of locks to protect buf_pool->page_hash */
242ulong srv_n_page_hash_locks = 16;
243/** innodb_lru_scan_depth; number of blocks scanned in LRU flush batch */
244ulong srv_LRU_scan_depth;
245/** innodb_flush_neighbors; whether or not to flush neighbors of a block */
246ulong srv_flush_neighbors;
247/** Previously requested size */
248ulint srv_buf_pool_old_size;
249/** Current size as scaling factor for the other components */
250ulint srv_buf_pool_base_size;
251/** Current size in bytes */
252ulint srv_buf_pool_curr_size;
253/** Dump this % of each buffer pool during BP dump */
254ulong srv_buf_pool_dump_pct;
255/** Abort load after this amount of pages */
256#ifdef UNIV_DEBUG
257ulong srv_buf_pool_load_pages_abort = LONG_MAX;
258#endif
259/** Lock table size in bytes */
260ulint srv_lock_table_size = ULINT_MAX;
261
262/** innodb_idle_flush_pct */
263ulong srv_idle_flush_pct;
264
265/** innodb_read_io_threads */
266ulong srv_n_read_io_threads;
267/** innodb_write_io_threads */
268ulong srv_n_write_io_threads;
269
270/** innodb_random_read_ahead */
271my_bool srv_random_read_ahead;
272/** innodb_read_ahead_threshold; the number of pages that must be present
273in the buffer cache and accessed sequentially for InnoDB to trigger a
274readahead request. */
275ulong srv_read_ahead_threshold;
276
277/** innodb_change_buffer_max_size; maximum on-disk size of change
278buffer in terms of percentage of the buffer pool. */
279uint srv_change_buffer_max_size;
280
281ulong srv_file_flush_method;
282
283
284/** copy of innodb_open_files; @see innodb_init_params() */
285ulint srv_max_n_open_files;
286
287/** innodb_io_capacity */
288ulong srv_io_capacity;
289/** innodb_io_capacity_max */
290ulong srv_max_io_capacity;
291
292/** innodb_page_cleaners; the number of page cleaner threads */
293ulong srv_n_page_cleaners;
294
295/* The InnoDB main thread tries to keep the ratio of modified pages
296in the buffer pool to all database pages in the buffer pool smaller than
297the following number. But it is not guaranteed that the value stays below
298that during a time of heavy update/insert activity. */
299
300/** innodb_max_dirty_pages_pct */
301double srv_max_buf_pool_modified_pct;
302/** innodb_max_dirty_pages_pct_lwm */
303double srv_max_dirty_pages_pct_lwm;
304
305/** innodb_adaptive_flushing_lwm; the percentage of log capacity at
306which adaptive flushing, if enabled, will kick in. */
307double srv_adaptive_flushing_lwm;
308
309/** innodb_flushing_avg_loops; number of iterations over which
310adaptive flushing is averaged */
311ulong srv_flushing_avg_loops;
312
313/** innodb_purge_threads; the number of purge threads to use */
314ulong srv_n_purge_threads;
315
316/** innodb_purge_batch_size, in pages */
317ulong srv_purge_batch_size;
318
319/** innodb_stats_method decides how InnoDB treats
320NULL value when collecting statistics. By default, it is set to
321SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */
322ulong srv_innodb_stats_method;
323
324srv_stats_t srv_stats;
325
326/* structure to pass status variables to MySQL */
327export_var_t export_vars;
328
329/** Normally 0. When nonzero, skip some phases of crash recovery,
330starting from SRV_FORCE_IGNORE_CORRUPT, so that data can be recovered
331by SELECT or mysqldump. When this is nonzero, we do not allow any user
332modifications to the data. */
333ulong srv_force_recovery;
334
335/** innodb_print_all_deadlocks; whether to print all user-level
336transactions deadlocks to the error log */
337my_bool srv_print_all_deadlocks;
338
339/** innodb_cmp_per_index_enabled; enable
340INFORMATION_SCHEMA.innodb_cmp_per_index */
341my_bool srv_cmp_per_index_enabled;
342
343/** innodb_fast_shutdown; if 1 then we do not run purge and insert buffer
344merge to completion before shutdown. If it is set to 2, do not even flush the
345buffer pool to data files at the shutdown: we effectively 'crash'
346InnoDB (but lose no committed transactions). */
347uint srv_fast_shutdown;
348
349/** copy of innodb_status_file; generate a innodb_status.<pid> file */
350ibool srv_innodb_status;
351
352/** innodb_prefix_index_cluster_optimization; whether to optimize
353prefix index queries to skip cluster index lookup when possible */
354my_bool srv_prefix_index_cluster_optimization;
355
356/** innodb_stats_transient_sample_pages;
357When estimating number of different key values in an index, sample
358this many index pages, there are 2 ways to calculate statistics:
359* persistent stats that are calculated by ANALYZE TABLE and saved
360 in the innodb database.
361* quick transient stats, that are used if persistent stats for the given
362 table/index are not found in the innodb database */
363unsigned long long srv_stats_transient_sample_pages;
364/** innodb_stats_persistent */
365my_bool srv_stats_persistent;
366/** innodb_stats_include_delete_marked */
367my_bool srv_stats_include_delete_marked;
368/** innodb_stats_persistent_sample_pages */
369unsigned long long srv_stats_persistent_sample_pages;
370/** innodb_stats_auto_recalc */
371my_bool srv_stats_auto_recalc;
372
373/** innodb_stats_modified_counter; The number of rows modified before
374we calculate new statistics (default 0 = current limits) */
375unsigned long long srv_stats_modified_counter;
376
377/** innodb_stats_traditional; enable traditional statistic calculation
378based on number of configured pages */
379my_bool srv_stats_sample_traditional;
380
381my_bool srv_use_doublewrite_buf;
382
383/** innodb_doublewrite_batch_size (a debug parameter) specifies the
384number of pages to use in LRU and flush_list batch flushing.
385The rest of the doublewrite buffer is used for single-page flushing. */
386ulong srv_doublewrite_batch_size = 120;
387
388/** innodb_replication_delay */
389ulong srv_replication_delay;
390
391/** innodb_sync_spin_loops */
392ulong srv_n_spin_wait_rounds;
393/** innodb_spin_wait_delay */
394uint srv_spin_wait_delay;
395
396static ulint srv_n_rows_inserted_old;
397static ulint srv_n_rows_updated_old;
398static ulint srv_n_rows_deleted_old;
399static ulint srv_n_rows_read_old;
400static ulint srv_n_system_rows_inserted_old;
401static ulint srv_n_system_rows_updated_old;
402static ulint srv_n_system_rows_deleted_old;
403static ulint srv_n_system_rows_read_old;
404
405ulint srv_truncated_status_writes;
406/** Number of initialized rollback segments for persistent undo log */
407ulong srv_available_undo_logs;
408
409/* Defragmentation */
410UNIV_INTERN my_bool srv_defragment;
411/** innodb_defragment_n_pages */
412UNIV_INTERN uint srv_defragment_n_pages;
413UNIV_INTERN uint srv_defragment_stats_accuracy;
414/** innodb_defragment_fill_factor_n_recs */
415UNIV_INTERN uint srv_defragment_fill_factor_n_recs;
416/** innodb_defragment_fill_factor */
417UNIV_INTERN double srv_defragment_fill_factor;
418/** innodb_defragment_frequency */
419UNIV_INTERN uint srv_defragment_frequency;
420/** derived from innodb_defragment_frequency;
421@see innodb_defragment_frequency_update() */
422UNIV_INTERN ulonglong srv_defragment_interval;
423
424/** Current mode of operation */
425UNIV_INTERN enum srv_operation_mode srv_operation;
426
427/* Set the following to 0 if you want InnoDB to write messages on
428stderr on startup/shutdown. Not enabled on the embedded server. */
429ibool srv_print_verbose_log;
430my_bool srv_print_innodb_monitor;
431my_bool srv_print_innodb_lock_monitor;
432/** innodb_force_primary_key; whether to disallow CREATE TABLE without
433PRIMARY KEY */
434my_bool srv_force_primary_key;
435
436/* Array of English strings describing the current state of an
437i/o handler thread */
438
439const char* srv_io_thread_op_info[SRV_MAX_N_IO_THREADS];
440const char* srv_io_thread_function[SRV_MAX_N_IO_THREADS];
441
442static time_t srv_last_monitor_time;
443
444static ib_mutex_t srv_innodb_monitor_mutex;
445
446/** Mutex protecting page_zip_stat_per_index */
447ib_mutex_t page_zip_stat_per_index_mutex;
448
449/* Mutex for locking srv_monitor_file. Not created if srv_read_only_mode */
450ib_mutex_t srv_monitor_file_mutex;
451
452/** Temporary file for innodb monitor output */
453FILE* srv_monitor_file;
454/** Mutex for locking srv_misc_tmpfile. Not created if srv_read_only_mode.
455This mutex has a very low rank; threads reserving it should not
456acquire any further latches or sleep before releasing this one. */
457ib_mutex_t srv_misc_tmpfile_mutex;
458/** Temporary file for miscellanous diagnostic output */
459FILE* srv_misc_tmpfile;
460
461static ulint srv_main_thread_process_no;
462static ulint srv_main_thread_id;
463
464/* The following counts are used by the srv_master_thread. */
465
466/** Iterations of the loop bounded by 'srv_active' label. */
467static ulint srv_main_active_loops;
468/** Iterations of the loop bounded by the 'srv_idle' label. */
469static ulint srv_main_idle_loops;
470/** Iterations of the loop bounded by the 'srv_shutdown' label. */
471static ulint srv_main_shutdown_loops;
472/** Log writes involving flush. */
473static ulint srv_log_writes_and_flush;
474
475/* This is only ever touched by the master thread. It records the
476time when the last flush of log file has happened. The master
477thread ensures that we flush the log files at least once per
478second. */
479static time_t srv_last_log_flush_time;
480
481/* Interval in seconds at which various tasks are performed by the
482master thread when server is active. In order to balance the workload,
483we should try to keep intervals such that they are not multiple of
484each other. For example, if we have intervals for various tasks
485defined as 5, 10, 15, 60 then all tasks will be performed when
486current_time % 60 == 0 and no tasks will be performed when
487current_time % 5 != 0. */
488
489# define SRV_MASTER_CHECKPOINT_INTERVAL (7)
490# define SRV_MASTER_PURGE_INTERVAL (10)
491# define SRV_MASTER_DICT_LRU_INTERVAL (47)
492
493/** Simulate compression failures. */
494UNIV_INTERN uint srv_simulate_comp_failures;
495
496/** Buffer pool dump status frequence in percentages */
497UNIV_INTERN ulong srv_buf_dump_status_frequency;
498
499/** Acquire the system_mutex. */
500#define srv_sys_mutex_enter() do { \
501 mutex_enter(&srv_sys.mutex); \
502} while (0)
503
504/** Test if the system mutex is owned. */
505#define srv_sys_mutex_own() (mutex_own(&srv_sys.mutex) \
506 && !srv_read_only_mode)
507
508/** Release the system mutex. */
509#define srv_sys_mutex_exit() do { \
510 mutex_exit(&srv_sys.mutex); \
511} while (0)
512
513/*
514 IMPLEMENTATION OF THE SERVER MAIN PROGRAM
515 =========================================
516
517There is the following analogue between this database
518server and an operating system kernel:
519
520DB concept equivalent OS concept
521---------- ---------------------
522transaction -- process;
523
524query thread -- thread;
525
526lock -- semaphore;
527
528kernel -- kernel;
529
530query thread execution:
531(a) without lock mutex
532reserved -- process executing in user mode;
533(b) with lock mutex reserved
534 -- process executing in kernel mode;
535
536The server has several backgroind threads all running at the same
537priority as user threads. It periodically checks if here is anything
538happening in the server which requires intervention of the master
539thread. Such situations may be, for example, when flushing of dirty
540blocks is needed in the buffer pool or old version of database rows
541have to be cleaned away (purged). The user can configure a separate
542dedicated purge thread(s) too, in which case the master thread does not
543do any purging.
544
545The threads which we call user threads serve the queries of the MySQL
546server. They run at normal priority.
547
548When there is no activity in the system, also the master thread
549suspends itself to wait for an event making the server totally silent.
550
551There is still one complication in our server design. If a
552background utility thread obtains a resource (e.g., mutex) needed by a user
553thread, and there is also some other user activity in the system,
554the user thread may have to wait indefinitely long for the
555resource, as the OS does not schedule a background thread if
556there is some other runnable user thread. This problem is called
557priority inversion in real-time programming.
558
559One solution to the priority inversion problem would be to keep record
560of which thread owns which resource and in the above case boost the
561priority of the background thread so that it will be scheduled and it
562can release the resource. This solution is called priority inheritance
563in real-time programming. A drawback of this solution is that the overhead
564of acquiring a mutex increases slightly, maybe 0.2 microseconds on a 100
565MHz Pentium, because the thread has to call os_thread_get_curr_id. This may
566be compared to 0.5 microsecond overhead for a mutex lock-unlock pair. Note
567that the thread cannot store the information in the resource , say mutex,
568itself, because competing threads could wipe out the information if it is
569stored before acquiring the mutex, and if it stored afterwards, the
570information is outdated for the time of one machine instruction, at least.
571(To be precise, the information could be stored to lock_word in mutex if
572the machine supports atomic swap.)
573
574The above solution with priority inheritance may become actual in the
575future, currently we do not implement any priority twiddling solution.
576Our general aim is to reduce the contention of all mutexes by making
577them more fine grained.
578
579The thread table contains information of the current status of each
580thread existing in the system, and also the event semaphores used in
581suspending the master thread and utility threads when they have nothing
582to do. The thread table can be seen as an analogue to the process table
583in a traditional Unix implementation. */
584
585/** The server system struct */
586struct srv_sys_t{
587 ib_mutex_t tasks_mutex; /*!< variable protecting the
588 tasks queue */
589 UT_LIST_BASE_NODE_T(que_thr_t)
590 tasks; /*!< task queue */
591
592 ib_mutex_t mutex; /*!< variable protecting the
593 fields below. */
594 ulint n_sys_threads; /*!< size of the sys_threads
595 array */
596
597 srv_slot_t sys_threads[32 + 1]; /*!< server thread table;
598 os_event_set() and
599 os_event_reset() on
600 sys_threads[]->event are
601 covered by srv_sys_t::mutex */
602
603 ulint n_threads_active[SRV_MASTER + 1];
604 /*!< number of threads active
605 in a thread class; protected
606 by both my_atomic_addlint()
607 and mutex */
608
609 srv_stats_t::ulint_ctr_1_t
610 activity_count; /*!< For tracking server
611 activity */
612};
613
614static srv_sys_t srv_sys;
615
616/** @return whether the purge coordinator thread is active */
617bool purge_sys_t::running()
618{
619 return my_atomic_loadlint(&srv_sys.n_threads_active[SRV_PURGE]);
620}
621
622/** Event to signal srv_monitor_thread. Not protected by a mutex.
623Set after setting srv_print_innodb_monitor. */
624os_event_t srv_monitor_event;
625
626/** Event to signal the shutdown of srv_error_monitor_thread.
627Not protected by a mutex. */
628os_event_t srv_error_event;
629
630/** Event for waking up buf_dump_thread. Not protected by a mutex.
631Set on shutdown or by buf_dump_start() or buf_load_start(). */
632os_event_t srv_buf_dump_event;
633
634/** Event to signal the buffer pool resize thread */
635os_event_t srv_buf_resize_event;
636
637/** The buffer pool dump/load file name */
638char* srv_buf_dump_filename;
639
640/** Boolean config knobs that tell InnoDB to dump the buffer pool at shutdown
641and/or load it during startup. */
642char srv_buffer_pool_dump_at_shutdown = TRUE;
643char srv_buffer_pool_load_at_startup = TRUE;
644
645/** Slot index in the srv_sys.sys_threads array for the purge thread. */
646static const ulint SRV_PURGE_SLOT = 1;
647
648/** Slot index in the srv_sys.sys_threads array for the master thread. */
649static const ulint SRV_MASTER_SLOT = 0;
650
651#ifdef HAVE_PSI_STAGE_INTERFACE
652/** Performance schema stage event for monitoring ALTER TABLE progress
653everything after flush log_make_checkpoint_at(). */
654PSI_stage_info srv_stage_alter_table_end
655 = {0, "alter table (end)", PSI_FLAG_STAGE_PROGRESS};
656
657/** Performance schema stage event for monitoring ALTER TABLE progress
658log_make_checkpoint_at(). */
659PSI_stage_info srv_stage_alter_table_flush
660 = {0, "alter table (flush)", PSI_FLAG_STAGE_PROGRESS};
661
662/** Performance schema stage event for monitoring ALTER TABLE progress
663row_merge_insert_index_tuples(). */
664PSI_stage_info srv_stage_alter_table_insert
665 = {0, "alter table (insert)", PSI_FLAG_STAGE_PROGRESS};
666
667/** Performance schema stage event for monitoring ALTER TABLE progress
668row_log_apply(). */
669PSI_stage_info srv_stage_alter_table_log_index
670 = {0, "alter table (log apply index)", PSI_FLAG_STAGE_PROGRESS};
671
672/** Performance schema stage event for monitoring ALTER TABLE progress
673row_log_table_apply(). */
674PSI_stage_info srv_stage_alter_table_log_table
675 = {0, "alter table (log apply table)", PSI_FLAG_STAGE_PROGRESS};
676
677/** Performance schema stage event for monitoring ALTER TABLE progress
678row_merge_sort(). */
679PSI_stage_info srv_stage_alter_table_merge_sort
680 = {0, "alter table (merge sort)", PSI_FLAG_STAGE_PROGRESS};
681
682/** Performance schema stage event for monitoring ALTER TABLE progress
683row_merge_read_clustered_index(). */
684PSI_stage_info srv_stage_alter_table_read_pk_internal_sort
685 = {0, "alter table (read PK and internal sort)", PSI_FLAG_STAGE_PROGRESS};
686
687/** Performance schema stage event for monitoring buffer pool load progress. */
688PSI_stage_info srv_stage_buffer_pool_load
689 = {0, "buffer pool load", PSI_FLAG_STAGE_PROGRESS};
690#endif /* HAVE_PSI_STAGE_INTERFACE */
691
692/*********************************************************************//**
693Prints counters for work done by srv_master_thread. */
694static
695void
696srv_print_master_thread_info(
697/*=========================*/
698 FILE *file) /* in: output stream */
699{
700 fprintf(file, "srv_master_thread loops: " ULINTPF " srv_active, "
701 ULINTPF " srv_shutdown, " ULINTPF " srv_idle\n"
702 "srv_master_thread log flush and writes: " ULINTPF "\n",
703 srv_main_active_loops,
704 srv_main_shutdown_loops,
705 srv_main_idle_loops,
706 srv_log_writes_and_flush);
707}
708
709/*********************************************************************//**
710Sets the info describing an i/o thread current state. */
711void
712srv_set_io_thread_op_info(
713/*======================*/
714 ulint i, /*!< in: the 'segment' of the i/o thread */
715 const char* str) /*!< in: constant char string describing the
716 state */
717{
718 ut_a(i < SRV_MAX_N_IO_THREADS);
719
720 srv_io_thread_op_info[i] = str;
721}
722
723/*********************************************************************//**
724Resets the info describing an i/o thread current state. */
725void
726srv_reset_io_thread_op_info()
727/*=========================*/
728{
729 for (ulint i = 0; i < UT_ARR_SIZE(srv_io_thread_op_info); ++i) {
730 srv_io_thread_op_info[i] = "not started yet";
731 }
732}
733
734#ifdef UNIV_DEBUG
735/*********************************************************************//**
736Validates the type of a thread table slot.
737@return TRUE if ok */
738static
739ibool
740srv_thread_type_validate(
741/*=====================*/
742 srv_thread_type type) /*!< in: thread type */
743{
744 switch (type) {
745 case SRV_NONE:
746 break;
747 case SRV_WORKER:
748 case SRV_PURGE:
749 case SRV_MASTER:
750 return(TRUE);
751 }
752 ut_error;
753 return(FALSE);
754}
755#endif /* UNIV_DEBUG */
756
757/*********************************************************************//**
758Gets the type of a thread table slot.
759@return thread type */
760static
761srv_thread_type
762srv_slot_get_type(
763/*==============*/
764 const srv_slot_t* slot) /*!< in: thread slot */
765{
766 srv_thread_type type = slot->type;
767 ut_ad(srv_thread_type_validate(type));
768 return(type);
769}
770
771/*********************************************************************//**
772Reserves a slot in the thread table for the current thread.
773@return reserved slot */
774static
775srv_slot_t*
776srv_reserve_slot(
777/*=============*/
778 srv_thread_type type) /*!< in: type of the thread */
779{
780 srv_slot_t* slot = 0;
781
782 srv_sys_mutex_enter();
783
784 ut_ad(srv_thread_type_validate(type));
785
786 switch (type) {
787 case SRV_MASTER:
788 slot = &srv_sys.sys_threads[SRV_MASTER_SLOT];
789 break;
790
791 case SRV_PURGE:
792 slot = &srv_sys.sys_threads[SRV_PURGE_SLOT];
793 break;
794
795 case SRV_WORKER:
796 /* Find an empty slot, skip the master and purge slots. */
797 for (slot = &srv_sys.sys_threads[2];
798 slot->in_use;
799 ++slot) {
800
801 ut_a(slot < &srv_sys.sys_threads[
802 srv_sys.n_sys_threads]);
803 }
804 break;
805
806 case SRV_NONE:
807 ut_error;
808 }
809
810 ut_a(!slot->in_use);
811
812 slot->in_use = TRUE;
813 slot->suspended = FALSE;
814 slot->type = type;
815
816 ut_ad(srv_slot_get_type(slot) == type);
817
818 my_atomic_addlint(&srv_sys.n_threads_active[type], 1);
819
820 srv_sys_mutex_exit();
821
822 return(slot);
823}
824
825/*********************************************************************//**
826Suspends the calling thread to wait for the event in its thread slot.
827@return the current signal count of the event. */
828static
829int64_t
830srv_suspend_thread_low(
831/*===================*/
832 srv_slot_t* slot) /*!< in/out: thread slot */
833{
834 ut_ad(!srv_read_only_mode);
835 ut_ad(srv_sys_mutex_own());
836
837 ut_ad(slot->in_use);
838
839 srv_thread_type type = srv_slot_get_type(slot);
840
841 switch (type) {
842 case SRV_NONE:
843 ut_error;
844
845 case SRV_MASTER:
846 /* We have only one master thread and it
847 should be the first entry always. */
848 ut_a(srv_sys.n_threads_active[type] == 1);
849 break;
850
851 case SRV_PURGE:
852 /* We have only one purge coordinator thread
853 and it should be the second entry always. */
854 ut_a(srv_sys.n_threads_active[type] == 1);
855 break;
856
857 case SRV_WORKER:
858 ut_a(srv_n_purge_threads > 1);
859 break;
860 }
861
862 ut_a(!slot->suspended);
863 slot->suspended = TRUE;
864
865 if (lint(my_atomic_addlint(&srv_sys.n_threads_active[type], ulint(-1)))
866 < 0) {
867 ut_error;
868 }
869
870 return(os_event_reset(slot->event));
871}
872
873/*********************************************************************//**
874Suspends the calling thread to wait for the event in its thread slot.
875@return the current signal count of the event. */
876static
877int64_t
878srv_suspend_thread(
879/*===============*/
880 srv_slot_t* slot) /*!< in/out: thread slot */
881{
882 srv_sys_mutex_enter();
883
884 int64_t sig_count = srv_suspend_thread_low(slot);
885
886 srv_sys_mutex_exit();
887
888 return(sig_count);
889}
890
891/** Resume the calling thread.
892@param[in,out] slot thread slot
893@param[in] sig_count signal count (if wait)
894@param[in] wait whether to wait for the event
895@param[in] timeout_usec timeout in microseconds (0=infinite)
896@return whether the wait timed out */
897static
898bool
899srv_resume_thread(srv_slot_t* slot, int64_t sig_count = 0, bool wait = true,
900 ulint timeout_usec = 0)
901{
902 bool timeout;
903
904 ut_ad(!srv_read_only_mode);
905 ut_ad(slot->in_use);
906 ut_ad(slot->suspended);
907
908 if (!wait) {
909 timeout = false;
910 } else if (timeout_usec) {
911 timeout = OS_SYNC_TIME_EXCEEDED == os_event_wait_time_low(
912 slot->event, timeout_usec, sig_count);
913 } else {
914 timeout = false;
915 os_event_wait_low(slot->event, sig_count);
916 }
917
918 srv_sys_mutex_enter();
919 ut_ad(slot->in_use);
920 ut_ad(slot->suspended);
921
922 slot->suspended = FALSE;
923 my_atomic_addlint(&srv_sys.n_threads_active[slot->type], 1);
924 srv_sys_mutex_exit();
925 return(timeout);
926}
927
928/** Ensure that a given number of threads of the type given are running
929(or are already terminated).
930@param[in] type thread type
931@param[in] n number of threads that have to run */
932void
933srv_release_threads(enum srv_thread_type type, ulint n)
934{
935 ulint running;
936
937 ut_ad(srv_thread_type_validate(type));
938 ut_ad(n > 0);
939
940 do {
941 running = 0;
942
943 srv_sys_mutex_enter();
944
945 for (ulint i = 0; i < srv_sys.n_sys_threads; i++) {
946 srv_slot_t* slot = &srv_sys.sys_threads[i];
947
948 if (!slot->in_use || srv_slot_get_type(slot) != type) {
949 continue;
950 } else if (!slot->suspended) {
951 if (++running >= n) {
952 break;
953 }
954 continue;
955 }
956
957 switch (type) {
958 case SRV_NONE:
959 ut_error;
960
961 case SRV_MASTER:
962 /* We have only one master thread and it
963 should be the first entry always. */
964 ut_a(n == 1);
965 ut_a(i == SRV_MASTER_SLOT);
966 ut_a(srv_sys.n_threads_active[type] == 0);
967 break;
968
969 case SRV_PURGE:
970 /* We have only one purge coordinator thread
971 and it should be the second entry always. */
972 ut_a(n == 1);
973 ut_a(i == SRV_PURGE_SLOT);
974 ut_a(srv_n_purge_threads > 0);
975 ut_a(srv_sys.n_threads_active[type] == 0);
976 break;
977
978 case SRV_WORKER:
979 ut_a(srv_n_purge_threads > 1);
980 ut_a(srv_sys.n_threads_active[type]
981 < srv_n_purge_threads - 1);
982 break;
983 }
984
985 os_event_set(slot->event);
986 }
987
988 srv_sys_mutex_exit();
989 } while (running && running < n);
990}
991
992/*********************************************************************//**
993Release a thread's slot. */
994static
995void
996srv_free_slot(
997/*==========*/
998 srv_slot_t* slot) /*!< in/out: thread slot */
999{
1000 srv_sys_mutex_enter();
1001
1002 /* Mark the thread as inactive. */
1003 srv_suspend_thread_low(slot);
1004 /* Free the slot for reuse. */
1005 ut_ad(slot->in_use);
1006 slot->in_use = FALSE;
1007
1008 srv_sys_mutex_exit();
1009}
1010
1011/** Initialize the server. */
1012static
1013void
1014srv_init()
1015{
1016 mutex_create(LATCH_ID_SRV_INNODB_MONITOR, &srv_innodb_monitor_mutex);
1017
1018 srv_sys.n_sys_threads = srv_read_only_mode
1019 ? 0
1020 : srv_n_purge_threads + 1/* purge coordinator */;
1021
1022 if (!srv_read_only_mode) {
1023 mutex_create(LATCH_ID_SRV_SYS, &srv_sys.mutex);
1024
1025 mutex_create(LATCH_ID_SRV_SYS_TASKS, &srv_sys.tasks_mutex);
1026
1027 for (ulint i = 0; i < srv_sys.n_sys_threads; ++i) {
1028 srv_slot_t* slot = &srv_sys.sys_threads[i];
1029
1030 slot->event = os_event_create(0);
1031
1032 ut_a(slot->event);
1033 }
1034
1035 srv_error_event = os_event_create(0);
1036
1037 srv_monitor_event = os_event_create(0);
1038
1039 srv_buf_dump_event = os_event_create(0);
1040
1041 buf_flush_event = os_event_create("buf_flush_event");
1042
1043 UT_LIST_INIT(srv_sys.tasks, &que_thr_t::queue);
1044 }
1045
1046 srv_buf_resize_event = os_event_create(0);
1047
1048 ut_d(srv_master_thread_disabled_event = os_event_create(0));
1049
1050 /* page_zip_stat_per_index_mutex is acquired from:
1051 1. page_zip_compress() (after SYNC_FSP)
1052 2. page_zip_decompress()
1053 3. i_s_cmp_per_index_fill_low() (where SYNC_DICT is acquired)
1054 4. innodb_cmp_per_index_update(), no other latches
1055 since we do not acquire any other latches while holding this mutex,
1056 it can have very low level. We pick SYNC_ANY_LATCH for it. */
1057 mutex_create(LATCH_ID_PAGE_ZIP_STAT_PER_INDEX,
1058 &page_zip_stat_per_index_mutex);
1059
1060 /* Create dummy indexes for infimum and supremum records */
1061
1062 dict_ind_init();
1063
1064#ifdef WITH_INNODB_DISALLOW_WRITES
1065 /* Writes have to be enabled on init or else we hang. Thus, we
1066 always set the event here regardless of innobase_disallow_writes.
1067 That flag will always be 0 at this point because it isn't settable
1068 via my.cnf or command line arg. */
1069 srv_allow_writes_event = os_event_create(0);
1070 os_event_set(srv_allow_writes_event);
1071#endif /* WITH_INNODB_DISALLOW_WRITES */
1072
1073 /* Initialize some INFORMATION SCHEMA internal structures */
1074 trx_i_s_cache_init(trx_i_s_cache);
1075
1076 ut_crc32_init();
1077
1078 dict_mem_init();
1079}
1080
1081/*********************************************************************//**
1082Frees the data structures created in srv_init(). */
1083void
1084srv_free(void)
1085/*==========*/
1086{
1087 if (!srv_buf_resize_event) {
1088 return;
1089 }
1090
1091 mutex_free(&srv_innodb_monitor_mutex);
1092 mutex_free(&page_zip_stat_per_index_mutex);
1093
1094 if (!srv_read_only_mode) {
1095 mutex_free(&srv_sys.mutex);
1096 mutex_free(&srv_sys.tasks_mutex);
1097
1098 for (ulint i = 0; i < srv_sys.n_sys_threads; ++i) {
1099 os_event_destroy(srv_sys.sys_threads[i].event);
1100 }
1101
1102 os_event_destroy(srv_error_event);
1103 os_event_destroy(srv_monitor_event);
1104 os_event_destroy(srv_buf_dump_event);
1105 os_event_destroy(buf_flush_event);
1106 }
1107
1108 os_event_destroy(srv_buf_resize_event);
1109
1110 ut_d(os_event_destroy(srv_master_thread_disabled_event));
1111
1112 dict_ind_free();
1113
1114 trx_i_s_cache_free(trx_i_s_cache);
1115}
1116
1117/*********************************************************************//**
1118Boots the InnoDB server. */
1119void
1120srv_boot(void)
1121/*==========*/
1122{
1123 sync_check_init();
1124 recv_sys_var_init();
1125 trx_pool_init();
1126 row_mysql_init();
1127 srv_init();
1128}
1129
1130/******************************************************************//**
1131Refreshes the values used to calculate per-second averages. */
1132static
1133void
1134srv_refresh_innodb_monitor_stats(void)
1135/*==================================*/
1136{
1137 mutex_enter(&srv_innodb_monitor_mutex);
1138
1139 time_t current_time = time(NULL);
1140
1141 if (difftime(current_time, srv_last_monitor_time) <= 60) {
1142 /* We referesh InnoDB Monitor values so that averages are
1143 printed from at most 60 last seconds */
1144 mutex_exit(&srv_innodb_monitor_mutex);
1145 return;
1146 }
1147
1148 srv_last_monitor_time = current_time;
1149
1150 os_aio_refresh_stats();
1151
1152#ifdef BTR_CUR_HASH_ADAPT
1153 btr_cur_n_sea_old = btr_cur_n_sea;
1154#endif /* BTR_CUR_HASH_ADAPT */
1155 btr_cur_n_non_sea_old = btr_cur_n_non_sea;
1156
1157 log_refresh_stats();
1158
1159 buf_refresh_io_stats_all();
1160
1161 srv_n_rows_inserted_old = srv_stats.n_rows_inserted;
1162 srv_n_rows_updated_old = srv_stats.n_rows_updated;
1163 srv_n_rows_deleted_old = srv_stats.n_rows_deleted;
1164 srv_n_rows_read_old = srv_stats.n_rows_read;
1165
1166 srv_n_system_rows_inserted_old = srv_stats.n_system_rows_inserted;
1167 srv_n_system_rows_updated_old = srv_stats.n_system_rows_updated;
1168 srv_n_system_rows_deleted_old = srv_stats.n_system_rows_deleted;
1169 srv_n_system_rows_read_old = srv_stats.n_system_rows_read;
1170
1171 mutex_exit(&srv_innodb_monitor_mutex);
1172}
1173
1174/******************************************************************//**
1175Outputs to a file the output of the InnoDB Monitor.
1176@return FALSE if not all information printed
1177due to failure to obtain necessary mutex */
1178ibool
1179srv_printf_innodb_monitor(
1180/*======================*/
1181 FILE* file, /*!< in: output stream */
1182 ibool nowait, /*!< in: whether to wait for the
1183 lock_sys_t:: mutex */
1184 ulint* trx_start_pos, /*!< out: file position of the start of
1185 the list of active transactions */
1186 ulint* trx_end) /*!< out: file position of the end of
1187 the list of active transactions */
1188{
1189 double time_elapsed;
1190 time_t current_time;
1191 ibool ret;
1192
1193 mutex_enter(&srv_innodb_monitor_mutex);
1194
1195 current_time = time(NULL);
1196
1197 /* We add 0.001 seconds to time_elapsed to prevent division
1198 by zero if two users happen to call SHOW ENGINE INNODB STATUS at the
1199 same time */
1200
1201 time_elapsed = difftime(current_time, srv_last_monitor_time)
1202 + 0.001;
1203
1204 srv_last_monitor_time = time(NULL);
1205
1206 fputs("\n=====================================\n", file);
1207
1208 ut_print_timestamp(file);
1209 fprintf(file,
1210 " INNODB MONITOR OUTPUT\n"
1211 "=====================================\n"
1212 "Per second averages calculated from the last %lu seconds\n",
1213 (ulong) time_elapsed);
1214
1215 fputs("-----------------\n"
1216 "BACKGROUND THREAD\n"
1217 "-----------------\n", file);
1218 srv_print_master_thread_info(file);
1219
1220 fputs("----------\n"
1221 "SEMAPHORES\n"
1222 "----------\n", file);
1223
1224 sync_print(file);
1225
1226 /* Conceptually, srv_innodb_monitor_mutex has a very high latching
1227 order level in sync0sync.h, while dict_foreign_err_mutex has a very
1228 low level 135. Therefore we can reserve the latter mutex here without
1229 a danger of a deadlock of threads. */
1230
1231 mutex_enter(&dict_foreign_err_mutex);
1232
1233 if (!srv_read_only_mode && ftell(dict_foreign_err_file) != 0L) {
1234 fputs("------------------------\n"
1235 "LATEST FOREIGN KEY ERROR\n"
1236 "------------------------\n", file);
1237 ut_copy_file(file, dict_foreign_err_file);
1238 }
1239
1240 mutex_exit(&dict_foreign_err_mutex);
1241
1242 /* Only if lock_print_info_summary proceeds correctly,
1243 before we call the lock_print_info_all_transactions
1244 to print all the lock information. IMPORTANT NOTE: This
1245 function acquires the lock mutex on success. */
1246 ret = lock_print_info_summary(file, nowait);
1247
1248 if (ret) {
1249 if (trx_start_pos) {
1250 long t = ftell(file);
1251 if (t < 0) {
1252 *trx_start_pos = ULINT_UNDEFINED;
1253 } else {
1254 *trx_start_pos = (ulint) t;
1255 }
1256 }
1257
1258 /* NOTE: If we get here then we have the lock mutex. This
1259 function will release the lock mutex that we acquired when
1260 we called the lock_print_info_summary() function earlier. */
1261
1262 lock_print_info_all_transactions(file);
1263
1264 if (trx_end) {
1265 long t = ftell(file);
1266 if (t < 0) {
1267 *trx_end = ULINT_UNDEFINED;
1268 } else {
1269 *trx_end = (ulint) t;
1270 }
1271 }
1272 }
1273
1274 fputs("--------\n"
1275 "FILE I/O\n"
1276 "--------\n", file);
1277 os_aio_print(file);
1278
1279 fputs("-------------------------------------\n"
1280 "INSERT BUFFER AND ADAPTIVE HASH INDEX\n"
1281 "-------------------------------------\n", file);
1282 ibuf_print(file);
1283
1284#ifdef BTR_CUR_HASH_ADAPT
1285 for (ulint i = 0; i < btr_ahi_parts; ++i) {
1286 const hash_table_t* table = btr_search_sys->hash_tables[i];
1287
1288 ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
1289 /* this is only used for buf_pool->page_hash */
1290 ut_ad(!table->heaps);
1291 /* this is used for the adaptive hash index */
1292 ut_ad(table->heap);
1293
1294 const mem_heap_t* heap = table->heap;
1295 /* The heap may change during the following call,
1296 so the data displayed may be garbage. We intentionally
1297 avoid acquiring btr_search_latches[] so that the
1298 diagnostic output will not stop here even in case another
1299 thread hangs while holding btr_search_latches[].
1300
1301 This should be safe from crashes, because
1302 table->heap will be pointing to the same object
1303 for the full lifetime of the server. Even during
1304 btr_search_disable() the heap will stay valid. */
1305 fprintf(file, "Hash table size " ULINTPF
1306 ", node heap has " ULINTPF " buffer(s)\n",
1307 table->n_cells, heap->base.count - !heap->free_block);
1308 }
1309
1310 fprintf(file,
1311 "%.2f hash searches/s, %.2f non-hash searches/s\n",
1312 (btr_cur_n_sea - btr_cur_n_sea_old)
1313 / time_elapsed,
1314 (btr_cur_n_non_sea - btr_cur_n_non_sea_old)
1315 / time_elapsed);
1316 btr_cur_n_sea_old = btr_cur_n_sea;
1317#else /* BTR_CUR_HASH_ADAPT */
1318 fprintf(file,
1319 "%.2f non-hash searches/s\n",
1320 (btr_cur_n_non_sea - btr_cur_n_non_sea_old)
1321 / time_elapsed);
1322#endif /* BTR_CUR_HASH_ADAPT */
1323 btr_cur_n_non_sea_old = btr_cur_n_non_sea;
1324
1325 fputs("---\n"
1326 "LOG\n"
1327 "---\n", file);
1328 log_print(file);
1329
1330 fputs("----------------------\n"
1331 "BUFFER POOL AND MEMORY\n"
1332 "----------------------\n", file);
1333 fprintf(file,
1334 "Total large memory allocated " ULINTPF "\n"
1335 "Dictionary memory allocated " ULINTPF "\n",
1336 os_total_large_mem_allocated,
1337 dict_sys_get_size());
1338
1339 buf_print_io(file);
1340
1341 fputs("--------------\n"
1342 "ROW OPERATIONS\n"
1343 "--------------\n", file);
1344 fprintf(file,
1345 ULINTPF " queries inside InnoDB, "
1346 ULINTPF " queries in queue\n",
1347 srv_conc_get_active_threads(),
1348 srv_conc_get_waiting_threads());
1349
1350 fprintf(file, ULINTPF " read views open inside InnoDB\n",
1351 trx_sys.view_count());
1352
1353 if (ulint n_reserved = fil_system.sys_space->n_reserved_extents) {
1354 fprintf(file,
1355 ULINTPF " tablespace extents now reserved for"
1356 " B-tree split operations\n",
1357 n_reserved);
1358 }
1359
1360 fprintf(file,
1361 "Process ID=" ULINTPF
1362 ", Main thread ID=" ULINTPF
1363 ", state: %s\n",
1364 srv_main_thread_process_no,
1365 srv_main_thread_id,
1366 srv_main_thread_op_info);
1367 fprintf(file,
1368 "Number of rows inserted " ULINTPF
1369 ", updated " ULINTPF
1370 ", deleted " ULINTPF
1371 ", read " ULINTPF "\n",
1372 (ulint) srv_stats.n_rows_inserted,
1373 (ulint) srv_stats.n_rows_updated,
1374 (ulint) srv_stats.n_rows_deleted,
1375 (ulint) srv_stats.n_rows_read);
1376 fprintf(file,
1377 "%.2f inserts/s, %.2f updates/s,"
1378 " %.2f deletes/s, %.2f reads/s\n",
1379 ((ulint) srv_stats.n_rows_inserted - srv_n_rows_inserted_old)
1380 / time_elapsed,
1381 ((ulint) srv_stats.n_rows_updated - srv_n_rows_updated_old)
1382 / time_elapsed,
1383 ((ulint) srv_stats.n_rows_deleted - srv_n_rows_deleted_old)
1384 / time_elapsed,
1385 ((ulint) srv_stats.n_rows_read - srv_n_rows_read_old)
1386 / time_elapsed);
1387 fprintf(file,
1388 "Number of system rows inserted " ULINTPF
1389 ", updated " ULINTPF ", deleted " ULINTPF
1390 ", read " ULINTPF "\n",
1391 (ulint) srv_stats.n_system_rows_inserted,
1392 (ulint) srv_stats.n_system_rows_updated,
1393 (ulint) srv_stats.n_system_rows_deleted,
1394 (ulint) srv_stats.n_system_rows_read);
1395 fprintf(file,
1396 "%.2f inserts/s, %.2f updates/s,"
1397 " %.2f deletes/s, %.2f reads/s\n",
1398 ((ulint) srv_stats.n_system_rows_inserted
1399 - srv_n_system_rows_inserted_old) / time_elapsed,
1400 ((ulint) srv_stats.n_system_rows_updated
1401 - srv_n_system_rows_updated_old) / time_elapsed,
1402 ((ulint) srv_stats.n_system_rows_deleted
1403 - srv_n_system_rows_deleted_old) / time_elapsed,
1404 ((ulint) srv_stats.n_system_rows_read
1405 - srv_n_system_rows_read_old) / time_elapsed);
1406 srv_n_rows_inserted_old = srv_stats.n_rows_inserted;
1407 srv_n_rows_updated_old = srv_stats.n_rows_updated;
1408 srv_n_rows_deleted_old = srv_stats.n_rows_deleted;
1409 srv_n_rows_read_old = srv_stats.n_rows_read;
1410 srv_n_system_rows_inserted_old = srv_stats.n_system_rows_inserted;
1411 srv_n_system_rows_updated_old = srv_stats.n_system_rows_updated;
1412 srv_n_system_rows_deleted_old = srv_stats.n_system_rows_deleted;
1413 srv_n_system_rows_read_old = srv_stats.n_system_rows_read;
1414
1415 fputs("----------------------------\n"
1416 "END OF INNODB MONITOR OUTPUT\n"
1417 "============================\n", file);
1418 mutex_exit(&srv_innodb_monitor_mutex);
1419 fflush(file);
1420
1421 return(ret);
1422}
1423
1424/******************************************************************//**
1425Function to pass InnoDB status variables to MySQL */
1426void
1427srv_export_innodb_status(void)
1428/*==========================*/
1429{
1430 buf_pool_stat_t stat;
1431 buf_pools_list_size_t buf_pools_list_size;
1432 ulint LRU_len;
1433 ulint free_len;
1434 ulint flush_list_len;
1435 fil_crypt_stat_t crypt_stat;
1436 btr_scrub_stat_t scrub_stat;
1437
1438 buf_get_total_stat(&stat);
1439 buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len);
1440 buf_get_total_list_size_in_bytes(&buf_pools_list_size);
1441 if (!srv_read_only_mode) {
1442 fil_crypt_total_stat(&crypt_stat);
1443 btr_scrub_total_stat(&scrub_stat);
1444 }
1445
1446 mutex_enter(&srv_innodb_monitor_mutex);
1447
1448 export_vars.innodb_data_pending_reads =
1449 ulint(MONITOR_VALUE(MONITOR_OS_PENDING_READS));
1450
1451 export_vars.innodb_data_pending_writes =
1452 ulint(MONITOR_VALUE(MONITOR_OS_PENDING_WRITES));
1453
1454 export_vars.innodb_data_pending_fsyncs =
1455 fil_n_pending_log_flushes
1456 + fil_n_pending_tablespace_flushes;
1457
1458 export_vars.innodb_data_fsyncs = os_n_fsyncs;
1459
1460 export_vars.innodb_data_read = srv_stats.data_read;
1461
1462 export_vars.innodb_data_reads = os_n_file_reads;
1463
1464 export_vars.innodb_data_writes = os_n_file_writes;
1465
1466 export_vars.innodb_data_written = srv_stats.data_written;
1467
1468 export_vars.innodb_buffer_pool_read_requests = stat.n_page_gets;
1469
1470 export_vars.innodb_buffer_pool_write_requests =
1471 srv_stats.buf_pool_write_requests;
1472
1473 export_vars.innodb_buffer_pool_wait_free =
1474 srv_stats.buf_pool_wait_free;
1475
1476 export_vars.innodb_buffer_pool_pages_flushed =
1477 srv_stats.buf_pool_flushed;
1478
1479 export_vars.innodb_buffer_pool_reads = srv_stats.buf_pool_reads;
1480
1481 export_vars.innodb_buffer_pool_read_ahead_rnd =
1482 stat.n_ra_pages_read_rnd;
1483
1484 export_vars.innodb_buffer_pool_read_ahead =
1485 stat.n_ra_pages_read;
1486
1487 export_vars.innodb_buffer_pool_read_ahead_evicted =
1488 stat.n_ra_pages_evicted;
1489
1490 export_vars.innodb_buffer_pool_pages_data = LRU_len;
1491
1492 export_vars.innodb_buffer_pool_bytes_data =
1493 buf_pools_list_size.LRU_bytes
1494 + buf_pools_list_size.unzip_LRU_bytes;
1495
1496 export_vars.innodb_buffer_pool_pages_dirty = flush_list_len;
1497
1498 export_vars.innodb_buffer_pool_bytes_dirty =
1499 buf_pools_list_size.flush_list_bytes;
1500
1501 export_vars.innodb_buffer_pool_pages_free = free_len;
1502
1503#ifdef UNIV_DEBUG
1504 export_vars.innodb_buffer_pool_pages_latched =
1505 buf_get_latched_pages_number();
1506#endif /* UNIV_DEBUG */
1507 export_vars.innodb_buffer_pool_pages_total = buf_pool_get_n_pages();
1508
1509 export_vars.innodb_buffer_pool_pages_misc =
1510 buf_pool_get_n_pages() - LRU_len - free_len;
1511
1512#ifdef HAVE_ATOMIC_BUILTINS
1513 export_vars.innodb_have_atomic_builtins = 1;
1514#else
1515 export_vars.innodb_have_atomic_builtins = 0;
1516#endif
1517
1518 export_vars.innodb_page_size = srv_page_size;
1519
1520 export_vars.innodb_log_waits = srv_stats.log_waits;
1521
1522 export_vars.innodb_os_log_written = srv_stats.os_log_written;
1523
1524 export_vars.innodb_os_log_fsyncs = fil_n_log_flushes;
1525
1526 export_vars.innodb_os_log_pending_fsyncs = fil_n_pending_log_flushes;
1527
1528 export_vars.innodb_os_log_pending_writes =
1529 srv_stats.os_log_pending_writes;
1530
1531 export_vars.innodb_log_write_requests = srv_stats.log_write_requests;
1532
1533 export_vars.innodb_log_writes = srv_stats.log_writes;
1534
1535 export_vars.innodb_dblwr_pages_written =
1536 srv_stats.dblwr_pages_written;
1537
1538 export_vars.innodb_dblwr_writes = srv_stats.dblwr_writes;
1539
1540 export_vars.innodb_pages_created = stat.n_pages_created;
1541
1542 export_vars.innodb_pages_read = stat.n_pages_read;
1543 export_vars.innodb_page0_read = srv_stats.page0_read;
1544
1545 export_vars.innodb_pages_written = stat.n_pages_written;
1546
1547 export_vars.innodb_row_lock_waits = srv_stats.n_lock_wait_count;
1548
1549 export_vars.innodb_row_lock_current_waits =
1550 srv_stats.n_lock_wait_current_count;
1551
1552 export_vars.innodb_row_lock_time = srv_stats.n_lock_wait_time / 1000;
1553
1554 if (srv_stats.n_lock_wait_count > 0) {
1555
1556 export_vars.innodb_row_lock_time_avg = (ulint)
1557 (srv_stats.n_lock_wait_time
1558 / 1000 / srv_stats.n_lock_wait_count);
1559
1560 } else {
1561 export_vars.innodb_row_lock_time_avg = 0;
1562 }
1563
1564 export_vars.innodb_row_lock_time_max =
1565 lock_sys.n_lock_max_wait_time / 1000;
1566
1567 export_vars.innodb_rows_read = srv_stats.n_rows_read;
1568
1569 export_vars.innodb_rows_inserted = srv_stats.n_rows_inserted;
1570
1571 export_vars.innodb_rows_updated = srv_stats.n_rows_updated;
1572
1573 export_vars.innodb_rows_deleted = srv_stats.n_rows_deleted;
1574
1575 export_vars.innodb_system_rows_read = srv_stats.n_system_rows_read;
1576
1577 export_vars.innodb_system_rows_inserted =
1578 srv_stats.n_system_rows_inserted;
1579
1580 export_vars.innodb_system_rows_updated =
1581 srv_stats.n_system_rows_updated;
1582
1583 export_vars.innodb_system_rows_deleted =
1584 srv_stats.n_system_rows_deleted;
1585
1586 export_vars.innodb_num_open_files = fil_n_file_opened;
1587
1588 export_vars.innodb_truncated_status_writes =
1589 srv_truncated_status_writes;
1590
1591 export_vars.innodb_available_undo_logs = srv_available_undo_logs;
1592 export_vars.innodb_page_compression_saved = srv_stats.page_compression_saved;
1593 export_vars.innodb_index_pages_written = srv_stats.index_pages_written;
1594 export_vars.innodb_non_index_pages_written = srv_stats.non_index_pages_written;
1595 export_vars.innodb_pages_page_compressed = srv_stats.pages_page_compressed;
1596 export_vars.innodb_page_compressed_trim_op = srv_stats.page_compressed_trim_op;
1597 export_vars.innodb_pages_page_decompressed = srv_stats.pages_page_decompressed;
1598 export_vars.innodb_pages_page_compression_error = srv_stats.pages_page_compression_error;
1599 export_vars.innodb_pages_decrypted = srv_stats.pages_decrypted;
1600 export_vars.innodb_pages_encrypted = srv_stats.pages_encrypted;
1601 export_vars.innodb_n_merge_blocks_encrypted = srv_stats.n_merge_blocks_encrypted;
1602 export_vars.innodb_n_merge_blocks_decrypted = srv_stats.n_merge_blocks_decrypted;
1603 export_vars.innodb_n_rowlog_blocks_encrypted = srv_stats.n_rowlog_blocks_encrypted;
1604 export_vars.innodb_n_rowlog_blocks_decrypted = srv_stats.n_rowlog_blocks_decrypted;
1605
1606 export_vars.innodb_defragment_compression_failures =
1607 btr_defragment_compression_failures;
1608 export_vars.innodb_defragment_failures = btr_defragment_failures;
1609 export_vars.innodb_defragment_count = btr_defragment_count;
1610
1611 export_vars.innodb_onlineddl_rowlog_rows = onlineddl_rowlog_rows;
1612 export_vars.innodb_onlineddl_rowlog_pct_used = onlineddl_rowlog_pct_used;
1613 export_vars.innodb_onlineddl_pct_progress = onlineddl_pct_progress;
1614
1615 export_vars.innodb_sec_rec_cluster_reads =
1616 srv_stats.n_sec_rec_cluster_reads;
1617 export_vars.innodb_sec_rec_cluster_reads_avoided =
1618 srv_stats.n_sec_rec_cluster_reads_avoided;
1619
1620 if (!srv_read_only_mode) {
1621 export_vars.innodb_encryption_rotation_pages_read_from_cache =
1622 crypt_stat.pages_read_from_cache;
1623 export_vars.innodb_encryption_rotation_pages_read_from_disk =
1624 crypt_stat.pages_read_from_disk;
1625 export_vars.innodb_encryption_rotation_pages_modified =
1626 crypt_stat.pages_modified;
1627 export_vars.innodb_encryption_rotation_pages_flushed =
1628 crypt_stat.pages_flushed;
1629 export_vars.innodb_encryption_rotation_estimated_iops =
1630 crypt_stat.estimated_iops;
1631 export_vars.innodb_encryption_key_requests =
1632 srv_stats.n_key_requests;
1633 export_vars.innodb_key_rotation_list_length =
1634 srv_stats.key_rotation_list_length;
1635
1636 export_vars.innodb_scrub_page_reorganizations =
1637 scrub_stat.page_reorganizations;
1638 export_vars.innodb_scrub_page_splits =
1639 scrub_stat.page_splits;
1640 export_vars.innodb_scrub_page_split_failures_underflow =
1641 scrub_stat.page_split_failures_underflow;
1642 export_vars.innodb_scrub_page_split_failures_out_of_filespace =
1643 scrub_stat.page_split_failures_out_of_filespace;
1644 export_vars.innodb_scrub_page_split_failures_missing_index =
1645 scrub_stat.page_split_failures_missing_index;
1646 export_vars.innodb_scrub_page_split_failures_unknown =
1647 scrub_stat.page_split_failures_unknown;
1648 export_vars.innodb_scrub_log = srv_stats.n_log_scrubs;
1649 }
1650
1651 mutex_exit(&srv_innodb_monitor_mutex);
1652}
1653
1654/*********************************************************************//**
1655A thread which prints the info output by various InnoDB monitors.
1656@return a dummy parameter */
1657extern "C"
1658os_thread_ret_t
1659DECLARE_THREAD(srv_monitor_thread)(void*)
1660{
1661 int64_t sig_count;
1662 double time_elapsed;
1663 time_t current_time;
1664 time_t last_monitor_time;
1665 ulint mutex_skipped;
1666 ibool last_srv_print_monitor;
1667
1668 ut_ad(!srv_read_only_mode);
1669
1670#ifdef UNIV_DEBUG_THREAD_CREATION
1671 ib::info() << "Lock timeout thread starts, id "
1672 << os_thread_pf(os_thread_get_curr_id());
1673#endif /* UNIV_DEBUG_THREAD_CREATION */
1674
1675#ifdef UNIV_PFS_THREAD
1676 pfs_register_thread(srv_monitor_thread_key);
1677#endif /* UNIV_PFS_THREAD */
1678
1679 srv_last_monitor_time = ut_time();
1680 last_monitor_time = ut_time();
1681 mutex_skipped = 0;
1682 last_srv_print_monitor = srv_print_innodb_monitor;
1683loop:
1684 /* Wake up every 5 seconds to see if we need to print
1685 monitor information or if signalled at shutdown. */
1686
1687 sig_count = os_event_reset(srv_monitor_event);
1688
1689 os_event_wait_time_low(srv_monitor_event, 5000000, sig_count);
1690
1691 current_time = ut_time();
1692
1693 time_elapsed = difftime(current_time, last_monitor_time);
1694
1695 if (time_elapsed > 15) {
1696 last_monitor_time = ut_time();
1697
1698 if (srv_print_innodb_monitor) {
1699 /* Reset mutex_skipped counter everytime
1700 srv_print_innodb_monitor changes. This is to
1701 ensure we will not be blocked by lock_sys.mutex
1702 for short duration information printing,
1703 such as requested by sync_array_print_long_waits() */
1704 if (!last_srv_print_monitor) {
1705 mutex_skipped = 0;
1706 last_srv_print_monitor = TRUE;
1707 }
1708
1709 if (!srv_printf_innodb_monitor(stderr,
1710 MUTEX_NOWAIT(mutex_skipped),
1711 NULL, NULL)) {
1712 mutex_skipped++;
1713 } else {
1714 /* Reset the counter */
1715 mutex_skipped = 0;
1716 }
1717 } else {
1718 last_srv_print_monitor = FALSE;
1719 }
1720
1721
1722 /* We don't create the temp files or associated
1723 mutexes in read-only-mode */
1724
1725 if (!srv_read_only_mode && srv_innodb_status) {
1726 mutex_enter(&srv_monitor_file_mutex);
1727 rewind(srv_monitor_file);
1728 if (!srv_printf_innodb_monitor(srv_monitor_file,
1729 MUTEX_NOWAIT(mutex_skipped),
1730 NULL, NULL)) {
1731 mutex_skipped++;
1732 } else {
1733 mutex_skipped = 0;
1734 }
1735
1736 os_file_set_eof(srv_monitor_file);
1737 mutex_exit(&srv_monitor_file_mutex);
1738 }
1739 }
1740
1741 srv_refresh_innodb_monitor_stats();
1742
1743 if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
1744 goto exit_func;
1745 }
1746
1747 if (srv_print_innodb_monitor
1748 || srv_print_innodb_lock_monitor) {
1749 goto loop;
1750 }
1751
1752 goto loop;
1753
1754exit_func:
1755 srv_monitor_active = false;
1756
1757 /* We count the number of threads in os_thread_exit(). A created
1758 thread should always use that to exit and not use return() to exit. */
1759
1760 os_thread_exit();
1761
1762 OS_THREAD_DUMMY_RETURN;
1763}
1764
1765/*********************************************************************//**
1766A thread which prints warnings about semaphore waits which have lasted
1767too long. These can be used to track bugs which cause hangs.
1768@return a dummy parameter */
1769extern "C"
1770os_thread_ret_t
1771DECLARE_THREAD(srv_error_monitor_thread)(void*)
1772{
1773 /* number of successive fatal timeouts observed */
1774 ulint fatal_cnt = 0;
1775 lsn_t old_lsn;
1776 lsn_t new_lsn;
1777 int64_t sig_count;
1778 /* longest waiting thread for a semaphore */
1779 os_thread_id_t waiter = os_thread_get_curr_id();
1780 os_thread_id_t old_waiter = waiter;
1781 /* the semaphore that is being waited for */
1782 const void* sema = NULL;
1783 const void* old_sema = NULL;
1784
1785 ut_ad(!srv_read_only_mode);
1786
1787 old_lsn = srv_start_lsn;
1788
1789#ifdef UNIV_DEBUG_THREAD_CREATION
1790 ib::info() << "Error monitor thread starts, id "
1791 << os_thread_pf(os_thread_get_curr_id());
1792#endif /* UNIV_DEBUG_THREAD_CREATION */
1793
1794#ifdef UNIV_PFS_THREAD
1795 pfs_register_thread(srv_error_monitor_thread_key);
1796#endif /* UNIV_PFS_THREAD */
1797
1798loop:
1799 /* Try to track a strange bug reported by Harald Fuchs and others,
1800 where the lsn seems to decrease at times */
1801
1802 if (log_peek_lsn(&new_lsn)) {
1803 if (new_lsn < old_lsn) {
1804 ib::error() << "Old log sequence number " << old_lsn << " was"
1805 << " greater than the new log sequence number "
1806 << new_lsn << ". Please submit a bug report to"
1807 " https://jira.mariadb.org/";
1808 ut_ad(0);
1809 }
1810
1811 old_lsn = new_lsn;
1812 }
1813
1814 /* Update the statistics collected for deciding LRU
1815 eviction policy. */
1816 buf_LRU_stat_update();
1817
1818 if (sync_array_print_long_waits(&waiter, &sema)
1819 && sema == old_sema && os_thread_eq(waiter, old_waiter)) {
1820#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES)
1821 if (os_event_is_set(srv_allow_writes_event)) {
1822#endif /* WITH_WSREP */
1823 fatal_cnt++;
1824#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES)
1825 } else {
1826 fprintf(stderr,
1827 "WSREP: avoiding InnoDB self crash due to long "
1828 "semaphore wait of > %lu seconds\n"
1829 "Server is processing SST donor operation, "
1830 "fatal_cnt now: " ULINTPF,
1831 srv_fatal_semaphore_wait_threshold, fatal_cnt);
1832 }
1833#endif /* WITH_WSREP */
1834 if (fatal_cnt > 10) {
1835 ib::fatal() << "Semaphore wait has lasted > "
1836 << srv_fatal_semaphore_wait_threshold
1837 << " seconds. We intentionally crash the"
1838 " server because it appears to be hung.";
1839 }
1840 } else {
1841 fatal_cnt = 0;
1842 old_waiter = waiter;
1843 old_sema = sema;
1844 }
1845
1846 /* Flush stderr so that a database user gets the output
1847 to possible MySQL error file */
1848
1849 fflush(stderr);
1850
1851 sig_count = os_event_reset(srv_error_event);
1852
1853 os_event_wait_time_low(srv_error_event, 1000000, sig_count);
1854
1855 if (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
1856
1857 goto loop;
1858 }
1859
1860 srv_error_monitor_active = false;
1861
1862 /* We count the number of threads in os_thread_exit(). A created
1863 thread should always use that to exit and not use return() to exit. */
1864
1865 os_thread_exit();
1866
1867 OS_THREAD_DUMMY_RETURN;
1868}
1869
1870/******************************************************************//**
1871Increment the server activity count. */
1872void
1873srv_inc_activity_count(void)
1874/*========================*/
1875{
1876 srv_sys.activity_count.inc();
1877}
1878
1879/**********************************************************************//**
1880Check whether any background thread is active. If so return the thread
1881type.
1882@return SRV_NONE if all are suspended or have exited, thread
1883type if any are still active. */
1884srv_thread_type
1885srv_get_active_thread_type(void)
1886/*============================*/
1887{
1888 srv_thread_type ret = SRV_NONE;
1889
1890 if (srv_read_only_mode) {
1891 return(SRV_NONE);
1892 }
1893
1894 srv_sys_mutex_enter();
1895
1896 for (ulint i = SRV_WORKER; i <= SRV_MASTER; ++i) {
1897 if (srv_sys.n_threads_active[i] != 0) {
1898 ret = static_cast<srv_thread_type>(i);
1899 break;
1900 }
1901 }
1902
1903 srv_sys_mutex_exit();
1904
1905 if (ret == SRV_NONE && purge_sys.enabled()) {
1906 ret = SRV_PURGE;
1907 }
1908
1909 return(ret);
1910}
1911
1912/** Wake up the InnoDB master thread if it was suspended (not sleeping). */
1913void
1914srv_active_wake_master_thread_low()
1915{
1916 ut_ad(!srv_read_only_mode);
1917 ut_ad(!srv_sys_mutex_own());
1918
1919 srv_inc_activity_count();
1920
1921 if (my_atomic_loadlint(&srv_sys.n_threads_active[SRV_MASTER]) == 0) {
1922 srv_slot_t* slot;
1923
1924 srv_sys_mutex_enter();
1925
1926 slot = &srv_sys.sys_threads[SRV_MASTER_SLOT];
1927
1928 /* Only if the master thread has been started. */
1929
1930 if (slot->in_use) {
1931 ut_a(srv_slot_get_type(slot) == SRV_MASTER);
1932 os_event_set(slot->event);
1933 }
1934
1935 srv_sys_mutex_exit();
1936 }
1937}
1938
1939/** Wake up the purge threads if there is work to do. */
1940void
1941srv_wake_purge_thread_if_not_active()
1942{
1943 ut_ad(!srv_sys_mutex_own());
1944
1945 if (purge_sys.enabled() && !purge_sys.paused()
1946 && !my_atomic_loadlint(&srv_sys.n_threads_active[SRV_PURGE])
1947 && trx_sys.history_size()) {
1948
1949 srv_release_threads(SRV_PURGE, 1);
1950 }
1951}
1952
1953/** Wake up the master thread if it is suspended or being suspended. */
1954void
1955srv_wake_master_thread()
1956{
1957 srv_inc_activity_count();
1958 srv_release_threads(SRV_MASTER, 1);
1959}
1960
1961/*******************************************************************//**
1962Get current server activity count. We don't hold srv_sys::mutex while
1963reading this value as it is only used in heuristics.
1964@return activity count. */
1965ulint
1966srv_get_activity_count(void)
1967/*========================*/
1968{
1969 return(srv_sys.activity_count);
1970}
1971
1972/*******************************************************************//**
1973Check if there has been any activity.
1974@return FALSE if no change in activity counter. */
1975ibool
1976srv_check_activity(
1977/*===============*/
1978 ulint old_activity_count) /*!< in: old activity count */
1979{
1980 return(srv_sys.activity_count != old_activity_count);
1981}
1982
1983/********************************************************************//**
1984The master thread is tasked to ensure that flush of log file happens
1985once every second in the background. This is to ensure that not more
1986than one second of trxs are lost in case of crash when
1987innodb_flush_logs_at_trx_commit != 1 */
1988static
1989void
1990srv_sync_log_buffer_in_background(void)
1991/*===================================*/
1992{
1993 time_t current_time = time(NULL);
1994
1995 srv_main_thread_op_info = "flushing log";
1996 if (difftime(current_time, srv_last_log_flush_time)
1997 >= srv_flush_log_at_timeout) {
1998 log_buffer_sync_in_background(true);
1999 srv_last_log_flush_time = current_time;
2000 srv_log_writes_and_flush++;
2001 }
2002}
2003
2004/********************************************************************//**
2005Make room in the table cache by evicting an unused table.
2006@return number of tables evicted. */
2007static
2008ulint
2009srv_master_evict_from_table_cache(
2010/*==============================*/
2011 ulint pct_check) /*!< in: max percent to check */
2012{
2013 ulint n_tables_evicted = 0;
2014
2015 rw_lock_x_lock(dict_operation_lock);
2016
2017 dict_mutex_enter_for_mysql();
2018
2019 n_tables_evicted = dict_make_room_in_cache(
2020 innobase_get_table_cache_size(), pct_check);
2021
2022 dict_mutex_exit_for_mysql();
2023
2024 rw_lock_x_unlock(dict_operation_lock);
2025
2026 return(n_tables_evicted);
2027}
2028
2029/*********************************************************************//**
2030This function prints progress message every 60 seconds during server
2031shutdown, for any activities that master thread is pending on. */
2032static
2033void
2034srv_shutdown_print_master_pending(
2035/*==============================*/
2036 ib_time_t* last_print_time, /*!< last time the function
2037 print the message */
2038 ulint n_tables_to_drop, /*!< number of tables to
2039 be dropped */
2040 ulint n_bytes_merged) /*!< number of change buffer
2041 just merged */
2042{
2043 ib_time_t current_time;
2044 double time_elapsed;
2045
2046 current_time = ut_time();
2047 time_elapsed = ut_difftime(current_time, *last_print_time);
2048
2049 if (time_elapsed > 60) {
2050 *last_print_time = current_time;
2051
2052 if (n_tables_to_drop) {
2053 ib::info() << "Waiting for " << n_tables_to_drop
2054 << " table(s) to be dropped";
2055 }
2056
2057 /* Check change buffer merge, we only wait for change buffer
2058 merge if it is a slow shutdown */
2059 if (!srv_fast_shutdown && n_bytes_merged) {
2060 ib::info() << "Waiting for change buffer merge to"
2061 " complete number of bytes of change buffer"
2062 " just merged: " << n_bytes_merged;
2063 }
2064 }
2065}
2066
2067#ifdef UNIV_DEBUG
2068/** Waits in loop as long as master thread is disabled (debug) */
2069static
2070void
2071srv_master_do_disabled_loop(void)
2072{
2073 if (!srv_master_thread_disabled_debug) {
2074 /* We return here to avoid changing op_info. */
2075 return;
2076 }
2077
2078 srv_main_thread_op_info = "disabled";
2079
2080 while (srv_master_thread_disabled_debug) {
2081 os_event_set(srv_master_thread_disabled_event);
2082 if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
2083 break;
2084 }
2085 os_thread_sleep(100000);
2086 }
2087
2088 srv_main_thread_op_info = "";
2089}
2090
2091/** Disables master thread. It's used by:
2092 SET GLOBAL innodb_master_thread_disabled_debug = 1 (0).
2093@param[in] save immediate result from check function */
2094void
2095srv_master_thread_disabled_debug_update(THD*, st_mysql_sys_var*, void*,
2096 const void* save)
2097{
2098 /* This method is protected by mutex, as every SET GLOBAL .. */
2099 ut_ad(srv_master_thread_disabled_event != NULL);
2100
2101 const bool disable = *static_cast<const my_bool*>(save);
2102
2103 const int64_t sig_count = os_event_reset(
2104 srv_master_thread_disabled_event);
2105
2106 srv_master_thread_disabled_debug = disable;
2107
2108 if (disable) {
2109 os_event_wait_low(
2110 srv_master_thread_disabled_event, sig_count);
2111 }
2112}
2113#endif /* UNIV_DEBUG */
2114
2115/*********************************************************************//**
2116Perform the tasks that the master thread is supposed to do when the
2117server is active. There are two types of tasks. The first category is
2118of such tasks which are performed at each inovcation of this function.
2119We assume that this function is called roughly every second when the
2120server is active. The second category is of such tasks which are
2121performed at some interval e.g.: purge, dict_LRU cleanup etc. */
2122static
2123void
2124srv_master_do_active_tasks(void)
2125/*============================*/
2126{
2127 ib_time_t cur_time = ut_time();
2128 uintmax_t counter_time = ut_time_us(NULL);
2129
2130 /* First do the tasks that we are suppose to do at each
2131 invocation of this function. */
2132
2133 ++srv_main_active_loops;
2134
2135 MONITOR_INC(MONITOR_MASTER_ACTIVE_LOOPS);
2136
2137 /* ALTER TABLE in MySQL requires on Unix that the table handler
2138 can drop tables lazily after there no longer are SELECT
2139 queries to them. */
2140 srv_main_thread_op_info = "doing background drop tables";
2141 row_drop_tables_for_mysql_in_background();
2142 MONITOR_INC_TIME_IN_MICRO_SECS(
2143 MONITOR_SRV_BACKGROUND_DROP_TABLE_MICROSECOND, counter_time);
2144
2145 ut_d(srv_master_do_disabled_loop());
2146
2147 if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
2148 return;
2149 }
2150
2151 /* make sure that there is enough reusable space in the redo
2152 log files */
2153 srv_main_thread_op_info = "checking free log space";
2154 log_free_check();
2155
2156 /* Do an ibuf merge */
2157 srv_main_thread_op_info = "doing insert buffer merge";
2158 counter_time = ut_time_us(NULL);
2159 ibuf_merge_in_background(false);
2160 MONITOR_INC_TIME_IN_MICRO_SECS(
2161 MONITOR_SRV_IBUF_MERGE_MICROSECOND, counter_time);
2162
2163 /* Flush logs if needed */
2164 srv_main_thread_op_info = "flushing log";
2165 srv_sync_log_buffer_in_background();
2166 MONITOR_INC_TIME_IN_MICRO_SECS(
2167 MONITOR_SRV_LOG_FLUSH_MICROSECOND, counter_time);
2168
2169 /* Now see if various tasks that are performed at defined
2170 intervals need to be performed. */
2171
2172 if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
2173 return;
2174 }
2175
2176 if (cur_time % SRV_MASTER_DICT_LRU_INTERVAL == 0) {
2177 srv_main_thread_op_info = "enforcing dict cache limit";
2178 ulint n_evicted = srv_master_evict_from_table_cache(50);
2179 if (n_evicted != 0) {
2180 MONITOR_INC_VALUE(
2181 MONITOR_SRV_DICT_LRU_EVICT_COUNT_ACTIVE, n_evicted);
2182 }
2183 MONITOR_INC_TIME_IN_MICRO_SECS(
2184 MONITOR_SRV_DICT_LRU_MICROSECOND, counter_time);
2185 }
2186
2187 if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
2188 return;
2189 }
2190
2191 /* Make a new checkpoint */
2192 if (cur_time % SRV_MASTER_CHECKPOINT_INTERVAL == 0) {
2193 srv_main_thread_op_info = "making checkpoint";
2194 log_checkpoint(TRUE, FALSE);
2195 MONITOR_INC_TIME_IN_MICRO_SECS(
2196 MONITOR_SRV_CHECKPOINT_MICROSECOND, counter_time);
2197 }
2198}
2199
2200/*********************************************************************//**
2201Perform the tasks that the master thread is supposed to do whenever the
2202server is idle. We do check for the server state during this function
2203and if the server has entered the shutdown phase we may return from
2204the function without completing the required tasks.
2205Note that the server can move to active state when we are executing this
2206function but we don't check for that as we are suppose to perform more
2207or less same tasks when server is active. */
2208static
2209void
2210srv_master_do_idle_tasks(void)
2211/*==========================*/
2212{
2213 uintmax_t counter_time;
2214
2215 ++srv_main_idle_loops;
2216
2217 MONITOR_INC(MONITOR_MASTER_IDLE_LOOPS);
2218
2219
2220 /* ALTER TABLE in MySQL requires on Unix that the table handler
2221 can drop tables lazily after there no longer are SELECT
2222 queries to them. */
2223 counter_time = ut_time_us(NULL);
2224 srv_main_thread_op_info = "doing background drop tables";
2225 row_drop_tables_for_mysql_in_background();
2226 MONITOR_INC_TIME_IN_MICRO_SECS(
2227 MONITOR_SRV_BACKGROUND_DROP_TABLE_MICROSECOND,
2228 counter_time);
2229
2230 ut_d(srv_master_do_disabled_loop());
2231
2232 if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
2233 return;
2234 }
2235
2236 /* make sure that there is enough reusable space in the redo
2237 log files */
2238 srv_main_thread_op_info = "checking free log space";
2239 log_free_check();
2240
2241 /* Do an ibuf merge */
2242 counter_time = ut_time_us(NULL);
2243 srv_main_thread_op_info = "doing insert buffer merge";
2244 ibuf_merge_in_background(true);
2245 MONITOR_INC_TIME_IN_MICRO_SECS(
2246 MONITOR_SRV_IBUF_MERGE_MICROSECOND, counter_time);
2247
2248 if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
2249 return;
2250 }
2251
2252 srv_main_thread_op_info = "enforcing dict cache limit";
2253 ulint n_evicted = srv_master_evict_from_table_cache(100);
2254 if (n_evicted != 0) {
2255 MONITOR_INC_VALUE(
2256 MONITOR_SRV_DICT_LRU_EVICT_COUNT_IDLE, n_evicted);
2257 }
2258 MONITOR_INC_TIME_IN_MICRO_SECS(
2259 MONITOR_SRV_DICT_LRU_MICROSECOND, counter_time);
2260
2261 /* Flush logs if needed */
2262 srv_sync_log_buffer_in_background();
2263 MONITOR_INC_TIME_IN_MICRO_SECS(
2264 MONITOR_SRV_LOG_FLUSH_MICROSECOND, counter_time);
2265
2266 if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
2267 return;
2268 }
2269
2270 /* Make a new checkpoint */
2271 srv_main_thread_op_info = "making checkpoint";
2272 log_checkpoint(TRUE, FALSE);
2273 MONITOR_INC_TIME_IN_MICRO_SECS(MONITOR_SRV_CHECKPOINT_MICROSECOND,
2274 counter_time);
2275}
2276
2277/** Perform shutdown tasks.
2278@param[in] ibuf_merge whether to complete the change buffer merge */
2279static
2280void
2281srv_shutdown(bool ibuf_merge)
2282{
2283 ulint n_bytes_merged = 0;
2284 ulint n_tables_to_drop;
2285 ib_time_t now = ut_time();
2286
2287 do {
2288 ut_ad(!srv_read_only_mode);
2289 ut_ad(srv_shutdown_state == SRV_SHUTDOWN_CLEANUP);
2290 ++srv_main_shutdown_loops;
2291
2292 /* FIXME: Remove the background DROP TABLE queue; it is not
2293 crash-safe and breaks ACID. */
2294 srv_main_thread_op_info = "doing background drop tables";
2295 n_tables_to_drop = row_drop_tables_for_mysql_in_background();
2296
2297 if (ibuf_merge) {
2298 srv_main_thread_op_info = "checking free log space";
2299 log_free_check();
2300 srv_main_thread_op_info = "doing insert buffer merge";
2301 n_bytes_merged = ibuf_merge_in_background(true);
2302
2303 /* Flush logs if needed */
2304 srv_sync_log_buffer_in_background();
2305 }
2306
2307 /* Print progress message every 60 seconds during shutdown */
2308 if (srv_print_verbose_log) {
2309 srv_shutdown_print_master_pending(
2310 &now, n_tables_to_drop, n_bytes_merged);
2311 }
2312 } while (n_bytes_merged || n_tables_to_drop);
2313}
2314
2315/*********************************************************************//**
2316Puts master thread to sleep. At this point we are using polling to
2317service various activities. Master thread sleeps for one second before
2318checking the state of the server again */
2319static
2320void
2321srv_master_sleep(void)
2322/*==================*/
2323{
2324 srv_main_thread_op_info = "sleeping";
2325 os_thread_sleep(1000000);
2326 srv_main_thread_op_info = "";
2327}
2328
2329/*********************************************************************//**
2330The master thread controlling the server.
2331@return a dummy parameter */
2332extern "C"
2333os_thread_ret_t
2334DECLARE_THREAD(srv_master_thread)(
2335/*==============================*/
2336 void* arg MY_ATTRIBUTE((unused)))
2337 /*!< in: a dummy parameter required by
2338 os_thread_create */
2339{
2340 my_thread_init();
2341 DBUG_ENTER("srv_master_thread");
2342
2343 srv_slot_t* slot;
2344 ulint old_activity_count = srv_get_activity_count();
2345
2346 ut_ad(!srv_read_only_mode);
2347
2348#ifdef UNIV_DEBUG_THREAD_CREATION
2349 ib::info() << "Master thread starts, id "
2350 << os_thread_pf(os_thread_get_curr_id());
2351#endif /* UNIV_DEBUG_THREAD_CREATION */
2352
2353#ifdef UNIV_PFS_THREAD
2354 pfs_register_thread(srv_master_thread_key);
2355#endif /* UNIV_PFS_THREAD */
2356
2357 srv_main_thread_process_no = os_proc_get_number();
2358 srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
2359
2360 slot = srv_reserve_slot(SRV_MASTER);
2361 ut_a(slot == srv_sys.sys_threads);
2362
2363loop:
2364 while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
2365
2366 srv_master_sleep();
2367
2368 MONITOR_INC(MONITOR_MASTER_THREAD_SLEEP);
2369
2370 if (srv_check_activity(old_activity_count)) {
2371 old_activity_count = srv_get_activity_count();
2372 srv_master_do_active_tasks();
2373 } else {
2374 srv_master_do_idle_tasks();
2375 }
2376 }
2377
2378 switch (srv_shutdown_state) {
2379 case SRV_SHUTDOWN_NONE:
2380 break;
2381 case SRV_SHUTDOWN_FLUSH_PHASE:
2382 case SRV_SHUTDOWN_LAST_PHASE:
2383 ut_ad(0);
2384 /* fall through */
2385 case SRV_SHUTDOWN_EXIT_THREADS:
2386 /* srv_init_abort() must have been invoked */
2387 case SRV_SHUTDOWN_CLEANUP:
2388 if (srv_shutdown_state == SRV_SHUTDOWN_CLEANUP
2389 && srv_fast_shutdown < 2) {
2390 srv_shutdown(srv_fast_shutdown == 0);
2391 }
2392 srv_suspend_thread(slot);
2393 my_thread_end();
2394 os_thread_exit();
2395 }
2396
2397 srv_main_thread_op_info = "suspending";
2398
2399 srv_suspend_thread(slot);
2400
2401 srv_main_thread_op_info = "waiting for server activity";
2402
2403 srv_resume_thread(slot);
2404 goto loop;
2405}
2406
2407/** @return whether purge should exit due to shutdown */
2408static bool srv_purge_should_exit()
2409{
2410 ut_ad(srv_shutdown_state == SRV_SHUTDOWN_NONE
2411 || srv_shutdown_state == SRV_SHUTDOWN_CLEANUP);
2412
2413 if (srv_undo_sources) {
2414 return(false);
2415 }
2416 if (srv_fast_shutdown) {
2417 return(true);
2418 }
2419 /* Slow shutdown was requested. */
2420 return !trx_sys.any_active_transactions() && !trx_sys.history_size();
2421}
2422
2423/*********************************************************************//**
2424Fetch and execute a task from the work queue.
2425@return true if a task was executed */
2426static bool srv_task_execute()
2427{
2428 ut_ad(!srv_read_only_mode);
2429 ut_ad(srv_force_recovery < SRV_FORCE_NO_BACKGROUND);
2430
2431 mutex_enter(&srv_sys.tasks_mutex);
2432
2433 if (que_thr_t* thr = UT_LIST_GET_FIRST(srv_sys.tasks)) {
2434 ut_a(que_node_get_type(thr->child) == QUE_NODE_PURGE);
2435 UT_LIST_REMOVE(srv_sys.tasks, thr);
2436 mutex_exit(&srv_sys.tasks_mutex);
2437 que_run_threads(thr);
2438 my_atomic_addlint(&purge_sys.n_completed, 1);
2439 return true;
2440 }
2441
2442 ut_ad(UT_LIST_GET_LEN(srv_sys.tasks) == 0);
2443 mutex_exit(&srv_sys.tasks_mutex);
2444 return false;
2445}
2446
2447/*********************************************************************//**
2448Worker thread that reads tasks from the work queue and executes them.
2449@return a dummy parameter */
2450extern "C"
2451os_thread_ret_t
2452DECLARE_THREAD(srv_worker_thread)(
2453/*==============================*/
2454 void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
2455 required by os_thread_create */
2456{
2457 my_thread_init();
2458
2459 srv_slot_t* slot;
2460
2461 ut_ad(!srv_read_only_mode);
2462 ut_a(srv_force_recovery < SRV_FORCE_NO_BACKGROUND);
2463 my_thread_init();
2464 THD* thd = innobase_create_background_thd("InnoDB purge worker");
2465
2466#ifdef UNIV_DEBUG_THREAD_CREATION
2467 ib::info() << "Worker thread starting, id "
2468 << os_thread_pf(os_thread_get_curr_id());
2469#endif /* UNIV_DEBUG_THREAD_CREATION */
2470
2471 slot = srv_reserve_slot(SRV_WORKER);
2472
2473 ut_a(srv_n_purge_threads > 1);
2474 ut_a(ulong(my_atomic_loadlint(&srv_sys.n_threads_active[SRV_WORKER]))
2475 < srv_n_purge_threads);
2476
2477 /* We need to ensure that the worker threads exit after the
2478 purge coordinator thread. Otherwise the purge coordinator can
2479 end up waiting forever in trx_purge_wait_for_workers_to_complete() */
2480
2481 do {
2482 srv_suspend_thread(slot);
2483 srv_resume_thread(slot);
2484
2485 if (srv_task_execute()) {
2486
2487 /* If there are tasks in the queue, wakeup
2488 the purge coordinator thread. */
2489
2490 srv_wake_purge_thread_if_not_active();
2491 }
2492 } while (purge_sys.enabled());
2493
2494 srv_free_slot(slot);
2495
2496 ut_ad(!purge_sys.enabled());
2497
2498#ifdef UNIV_DEBUG_THREAD_CREATION
2499 ib::info() << "Purge worker thread exiting, id "
2500 << os_thread_pf(os_thread_get_curr_id());
2501#endif /* UNIV_DEBUG_THREAD_CREATION */
2502
2503 innobase_destroy_background_thd(thd);
2504 my_thread_end();
2505 /* We count the number of threads in os_thread_exit(). A created
2506 thread should always use that to exit and not use return() to exit. */
2507 os_thread_exit();
2508
2509 OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
2510}
2511
2512/** Do the actual purge operation.
2513@param[in,out] n_total_purged total number of purged pages
2514@return length of history list before the last purge batch. */
2515static
2516ulint
2517srv_do_purge(ulint* n_total_purged)
2518{
2519 ulint n_pages_purged;
2520
2521 static ulint count = 0;
2522 static ulint n_use_threads = 0;
2523 static ulint rseg_history_len = 0;
2524 ulint old_activity_count = srv_get_activity_count();
2525 const ulint n_threads = srv_n_purge_threads;
2526
2527 ut_a(n_threads > 0);
2528 ut_ad(!srv_read_only_mode);
2529
2530 /* Purge until there are no more records to purge and there is
2531 no change in configuration or server state. If the user has
2532 configured more than one purge thread then we treat that as a
2533 pool of threads and only use the extra threads if purge can't
2534 keep up with updates. */
2535
2536 if (n_use_threads == 0) {
2537 n_use_threads = n_threads;
2538 }
2539
2540 do {
2541 if (trx_sys.history_size() > rseg_history_len
2542 || (srv_max_purge_lag > 0
2543 && rseg_history_len > srv_max_purge_lag)) {
2544
2545 /* History length is now longer than what it was
2546 when we took the last snapshot. Use more threads. */
2547
2548 if (n_use_threads < n_threads) {
2549 ++n_use_threads;
2550 }
2551
2552 } else if (srv_check_activity(old_activity_count)
2553 && n_use_threads > 1) {
2554
2555 /* History length same or smaller since last snapshot,
2556 use fewer threads. */
2557
2558 --n_use_threads;
2559
2560 old_activity_count = srv_get_activity_count();
2561 }
2562
2563 /* Ensure that the purge threads are less than what
2564 was configured. */
2565
2566 ut_a(n_use_threads > 0);
2567 ut_a(n_use_threads <= n_threads);
2568
2569 /* Take a snapshot of the history list before purge. */
2570 if (!(rseg_history_len = trx_sys.history_size())) {
2571 break;
2572 }
2573
2574 ulint undo_trunc_freq =
2575 purge_sys.undo_trunc.get_rseg_truncate_frequency();
2576
2577 ulint rseg_truncate_frequency = ut_min(
2578 static_cast<ulint>(srv_purge_rseg_truncate_frequency),
2579 undo_trunc_freq);
2580
2581 n_pages_purged = trx_purge(
2582 n_use_threads,
2583 (++count % rseg_truncate_frequency) == 0);
2584
2585 *n_total_purged += n_pages_purged;
2586
2587 if (n_pages_purged) {
2588 service_manager_extend_timeout(
2589 INNODB_EXTEND_TIMEOUT_INTERVAL,
2590 "InnoDB " ULINTPF " pages purged", n_pages_purged);
2591 /* The previous round still did some work. */
2592 continue;
2593 }
2594 } while (n_pages_purged > 0 && !purge_sys.paused()
2595 && !srv_purge_should_exit());
2596
2597 return(rseg_history_len);
2598}
2599
2600/*********************************************************************//**
2601Suspend the purge coordinator thread. */
2602static
2603void
2604srv_purge_coordinator_suspend(
2605/*==========================*/
2606 srv_slot_t* slot, /*!< in/out: Purge coordinator
2607 thread slot */
2608 ulint rseg_history_len) /*!< in: history list length
2609 before last purge */
2610{
2611 ut_ad(!srv_read_only_mode);
2612 ut_a(slot->type == SRV_PURGE);
2613
2614 bool stop = false;
2615
2616 /** Maximum wait time on the purge event, in micro-seconds. */
2617 static const ulint SRV_PURGE_MAX_TIMEOUT = 10000;
2618
2619 int64_t sig_count = srv_suspend_thread(slot);
2620
2621 do {
2622 /* We don't wait right away on the the non-timed wait because
2623 we want to signal the thread that wants to suspend purge. */
2624 const bool wait = stop
2625 || rseg_history_len <= trx_sys.history_size();
2626 const bool timeout = srv_resume_thread(
2627 slot, sig_count, wait,
2628 stop ? 0 : SRV_PURGE_MAX_TIMEOUT);
2629
2630 sig_count = srv_suspend_thread(slot);
2631
2632 rw_lock_x_lock(&purge_sys.latch);
2633
2634 stop = srv_shutdown_state == SRV_SHUTDOWN_NONE
2635 && purge_sys.paused_latched();
2636
2637 if (!stop) {
2638 if (timeout
2639 && rseg_history_len < 5000
2640 && rseg_history_len == trx_sys.history_size()) {
2641 /* No new records were added since the
2642 wait started. Simply wait for new
2643 records. The magic number 5000 is an
2644 approximation for the case where we
2645 have cached UNDO log records which
2646 prevent truncate of the UNDO
2647 segments. */
2648 stop = true;
2649 }
2650 } else {
2651 /* Signal that we are suspended. */
2652 os_event_set(purge_sys.event);
2653 }
2654
2655 rw_lock_x_unlock(&purge_sys.latch);
2656 } while (stop && srv_undo_sources);
2657
2658 srv_resume_thread(slot, 0, false);
2659}
2660
2661/*********************************************************************//**
2662Purge coordinator thread that schedules the purge tasks.
2663@return a dummy parameter */
2664extern "C"
2665os_thread_ret_t
2666DECLARE_THREAD(srv_purge_coordinator_thread)(
2667/*=========================================*/
2668 void* arg MY_ATTRIBUTE((unused))) /*!< in: a dummy parameter
2669 required by os_thread_create */
2670{
2671 my_thread_init();
2672 THD* thd = innobase_create_background_thd("InnoDB purge coordinator");
2673 srv_slot_t* slot;
2674 ulint n_total_purged = ULINT_UNDEFINED;
2675
2676 ut_ad(!srv_read_only_mode);
2677 ut_a(srv_n_purge_threads >= 1);
2678 ut_a(srv_force_recovery < SRV_FORCE_NO_BACKGROUND);
2679
2680 purge_sys.coordinator_startup();
2681
2682#ifdef UNIV_PFS_THREAD
2683 pfs_register_thread(srv_purge_thread_key);
2684#endif /* UNIV_PFS_THREAD */
2685
2686#ifdef UNIV_DEBUG_THREAD_CREATION
2687 ib::info() << "Purge coordinator thread created, id "
2688 << os_thread_pf(os_thread_get_curr_id());
2689#endif /* UNIV_DEBUG_THREAD_CREATION */
2690
2691 slot = srv_reserve_slot(SRV_PURGE);
2692
2693 ulint rseg_history_len = trx_sys.history_size();
2694
2695 do {
2696 /* If there are no records to purge or the last
2697 purge didn't purge any records then wait for activity. */
2698
2699 if (srv_shutdown_state == SRV_SHUTDOWN_NONE
2700 && srv_undo_sources
2701 && (n_total_purged == 0 || purge_sys.paused())) {
2702
2703 srv_purge_coordinator_suspend(slot, rseg_history_len);
2704 }
2705
2706 ut_ad(!slot->suspended);
2707
2708 if (srv_purge_should_exit()) {
2709 break;
2710 }
2711
2712 n_total_purged = 0;
2713
2714 rseg_history_len = srv_do_purge(&n_total_purged);
2715 } while (!srv_purge_should_exit());
2716
2717 /* The task queue should always be empty, independent of fast
2718 shutdown state. */
2719 ut_a(srv_get_task_queue_length() == 0);
2720
2721 srv_free_slot(slot);
2722
2723 /* Note that we are shutting down. */
2724 rw_lock_x_lock(&purge_sys.latch);
2725 purge_sys.coordinator_shutdown();
2726
2727 /* If there are any pending undo-tablespace truncate then clear
2728 it off as we plan to shutdown the purge thread. */
2729 purge_sys.undo_trunc.clear();
2730
2731 /* Ensure that the wait in purge_sys_t::stop() will terminate. */
2732 os_event_set(purge_sys.event);
2733
2734 rw_lock_x_unlock(&purge_sys.latch);
2735
2736#ifdef UNIV_DEBUG_THREAD_CREATION
2737 ib::info() << "Purge coordinator exiting, id "
2738 << os_thread_pf(os_thread_get_curr_id());
2739#endif /* UNIV_DEBUG_THREAD_CREATION */
2740
2741 /* Ensure that all the worker threads quit. */
2742 if (ulint n_workers = srv_n_purge_threads - 1) {
2743 const srv_slot_t* slot;
2744 const srv_slot_t* const end = &srv_sys.sys_threads[
2745 srv_sys.n_sys_threads];
2746
2747 do {
2748 srv_release_threads(SRV_WORKER, n_workers);
2749 srv_sys_mutex_enter();
2750 for (slot = &srv_sys.sys_threads[2];
2751 !slot++->in_use && slot < end; );
2752 srv_sys_mutex_exit();
2753 } while (slot < end);
2754 }
2755
2756 innobase_destroy_background_thd(thd);
2757 my_thread_end();
2758 /* We count the number of threads in os_thread_exit(). A created
2759 thread should always use that to exit and not use return() to exit. */
2760 os_thread_exit();
2761
2762 OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
2763}
2764
2765/**********************************************************************//**
2766Enqueues a task to server task queue and releases a worker thread, if there
2767is a suspended one. */
2768void
2769srv_que_task_enqueue_low(
2770/*=====================*/
2771 que_thr_t* thr) /*!< in: query thread */
2772{
2773 ut_ad(!srv_read_only_mode);
2774 mutex_enter(&srv_sys.tasks_mutex);
2775
2776 UT_LIST_ADD_LAST(srv_sys.tasks, thr);
2777
2778 mutex_exit(&srv_sys.tasks_mutex);
2779
2780 srv_release_threads(SRV_WORKER, 1);
2781}
2782
2783/**********************************************************************//**
2784Get count of tasks in the queue.
2785@return number of tasks in queue */
2786ulint
2787srv_get_task_queue_length(void)
2788/*===========================*/
2789{
2790 ulint n_tasks;
2791
2792 ut_ad(!srv_read_only_mode);
2793
2794 mutex_enter(&srv_sys.tasks_mutex);
2795
2796 n_tasks = UT_LIST_GET_LEN(srv_sys.tasks);
2797
2798 mutex_exit(&srv_sys.tasks_mutex);
2799
2800 return(n_tasks);
2801}
2802
2803/** Wake up the purge threads. */
2804void
2805srv_purge_wakeup()
2806{
2807 ut_ad(!srv_read_only_mode);
2808 ut_ad(!sync_check_iterate(sync_check()));
2809
2810 if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
2811 return;
2812 }
2813
2814 do {
2815 srv_release_threads(SRV_PURGE, 1);
2816
2817 if (srv_n_purge_threads > 1) {
2818 ulint n_workers = srv_n_purge_threads - 1;
2819
2820 srv_release_threads(SRV_WORKER, n_workers);
2821 }
2822 } while (!my_atomic_loadptr_explicit(reinterpret_cast<void**>
2823 (&srv_running),
2824 MY_MEMORY_ORDER_RELAXED)
2825 && (srv_sys.n_threads_active[SRV_WORKER]
2826 || srv_sys.n_threads_active[SRV_PURGE]));
2827}
2828
2829/** Check if tablespace is being truncated.
2830(Ignore system-tablespace as we don't re-create the tablespace
2831and so some of the action that are suppressed by this function
2832for independent tablespace are not applicable to system-tablespace).
2833@param space_id space_id to check for truncate action
2834@return true if being truncated, false if not being
2835 truncated or tablespace is system-tablespace. */
2836bool
2837srv_is_tablespace_truncated(ulint space_id)
2838{
2839 if (is_system_tablespace(space_id)) {
2840 return(false);
2841 }
2842
2843 return(truncate_t::is_tablespace_truncated(space_id)
2844 || undo::Truncate::is_tablespace_truncated(space_id));
2845
2846}
2847
2848/** Check if tablespace was truncated.
2849@param[in] space space object to check for truncate action
2850@return true if tablespace was truncated and we still have an active
2851MLOG_TRUNCATE REDO log record. */
2852bool
2853srv_was_tablespace_truncated(const fil_space_t* space)
2854{
2855 if (space == NULL) {
2856 ut_ad(0);
2857 return(false);
2858 }
2859
2860 return (!is_system_tablespace(space->id)
2861 && truncate_t::was_tablespace_truncated(space->id));
2862}
2863