summaryrefslogtreecommitdiff
path: root/innobase/srv/srv0srv.c
diff options
context:
space:
mode:
authorunknown <monty@hundin.mysql.fi>2001-11-04 16:14:09 +0200
committerunknown <monty@hundin.mysql.fi>2001-11-04 16:14:09 +0200
commit0d1ba873aa11ea581ebbda9f450027329f2e1a3b (patch)
tree689c9d0271e23431f1ab0ac09e1af4d68a58ca76 /innobase/srv/srv0srv.c
parent9f90ff3f12f1fc2bcb70cde74dbd6f27e33e230c (diff)
parent0176dacd54b7eb62ebc4a81909b189517aee2cb4 (diff)
downloadmariadb-git-0d1ba873aa11ea581ebbda9f450027329f2e1a3b.tar.gz
merge with 3.23.44
BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union Docs/manual.texi: Auto merged include/my_base.h: Auto merged mysql-test/t/func_time.test: Auto merged mysql-test/t/join.test: Auto merged mysql-test/t/rpl000012.test: Auto merged BUILD/FINISH.sh: Auto merged BitKeeper/deleted/.del-db_ext.h~a1e210bbd0de0a48: Auto merged BitKeeper/deleted/.del-mutex_ext.h~f20f47ddc346598b: Auto merged BitKeeper/deleted/.del-violite.c~984c09cffe14a11b: Auto merged BitKeeper/deleted/.del-violite.c~d7b85be615595ace: Auto merged Build-tools/Do-all-build-steps: Auto merged client/client_priv.h: Auto merged client/mysqladmin.c: Auto merged innobase/include/srv0srv.h: Auto merged innobase/include/univ.i: Auto merged innobase/log/log0log.c: Auto merged innobase/srv/srv0srv.c: Auto merged innobase/srv/srv0start.c: Auto merged isam/pack_isam.c: Auto merged libmysql_r/Makefile.am: Auto merged myisam/myisamchk.c: Auto merged mysql-test/t/having.test: Auto merged mysql-test/t/rpl000015-slave.sh: Auto merged mysql-test/t/rpl000016-slave.sh: Auto merged mysys/mf_cache.c: Auto merged mysys/mf_casecnv.c: Auto merged mysys/mf_tempfile.c: Auto merged readline/vi_mode.c: Auto merged strings/strto.c: Auto merged sql/field.cc: Auto merged sql/field.h: Auto merged sql/ha_berkeley.cc: Auto merged sql/ha_myisammrg.cc: Auto merged sql/handler.cc: Auto merged sql/item.h: Auto merged sql/log_event.cc: Auto merged sql/sql_acl.cc: Auto merged sql/time.cc: Auto merged BUILD/SETUP.sh: Use -mcpu as default (safe for all x86 cpu's) client/mysqldump.c: Merge from 3.23.44 configure.in: Update version number extra/resolveip.c: Portability fix
Diffstat (limited to 'innobase/srv/srv0srv.c')
-rw-r--r--innobase/srv/srv0srv.c263
1 files changed, 249 insertions, 14 deletions
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 45f7b1b6879..a00f5c95c7c 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -24,7 +24,7 @@ thread library. This might confuse NT though.
Created 10/8/1995 Heikki Tuuri
*******************************************************/
-
+/* Dummy comment */
#include "srv0srv.h"
#include "ut0mem.h"
@@ -48,11 +48,15 @@ Created 10/8/1995 Heikki Tuuri
#include "buf0flu.h"
#include "btr0sea.h"
#include "dict0load.h"
+#include "srv0start.h"
/* The following counter is incremented whenever there is some user activity
in the server */
ulint srv_activity_count = 0;
+ibool srv_lock_timeout_and_monitor_active = FALSE;
+ibool srv_error_monitor_active = FALSE;
+
char* srv_main_thread_op_info = "";
/* Server parameters which are read from the initfile */
@@ -106,9 +110,48 @@ char* srv_unix_file_flush_method_str = NULL;
ulint srv_unix_file_flush_method = 0;
/* If the following is != 0 we do not allow inserts etc. This protects
-the user from forgetting innodb_force_recovery keyword to my.cnf */
+the user from forgetting the innodb_force_recovery keyword to my.cnf */
ulint srv_force_recovery = 0;
+/*-----------------------*/
+/* The following controls how many threads we let inside InnoDB concurrently:
+threads waiting for locks are not counted into the number because otherwise
+we could get a deadlock. MySQL creates a thread for each user session, and
+semaphore contention and convoy problems can occur withput this restriction.
+Value 10 should be good if there are less than 4 processors + 4 disks in the
+computer. Bigger computers need bigger values. */
+
+ulint srv_thread_concurrency = 4;
+
+os_fast_mutex_t srv_conc_mutex; /* this mutex protects srv_conc data
+ structures */
+ulint srv_conc_n_threads = 0; /* number of OS threads currently
+ inside InnoDB */
+
+typedef struct srv_conc_slot_struct srv_conc_slot_t;
+struct srv_conc_slot_struct{
+ os_event_t event; /* event to wait */
+ ibool reserved; /* TRUE if slot
+ reserved */
+ ibool wait_ended; /* TRUE when another
+ thread has already set
+ the event and the
+ thread in this slot is
+ free to proceed; but
+ reserved may still be
+ TRUE at that point */
+ UT_LIST_NODE_T(srv_conc_slot_t) srv_conc_queue; /* queue node */
+};
+
+UT_LIST_BASE_NODE_T(srv_conc_slot_t) srv_conc_queue; /* queue of threads
+ waiting to get in */
+srv_conc_slot_t srv_conc_slots[OS_THREAD_MAX_N]; /* array of wait
+ slots */
+/*-----------------------*/
+/* If the following is set TRUE then we do not run purge and insert buffer
+merge to completion before shutdown */
+
+ibool srv_fast_shutdown = FALSE;
ibool srv_use_doublewrite_buf = TRUE;
@@ -1512,8 +1555,9 @@ void
srv_init(void)
/*==========*/
{
- srv_slot_t* slot;
- ulint i;
+ srv_conc_slot_t* conc_slot;
+ srv_slot_t* slot;
+ ulint i;
srv_sys = mem_alloc(sizeof(srv_sys_t));
@@ -1556,6 +1600,19 @@ srv_init(void)
ut_a(srv_sys->operational);
UT_LIST_INIT(srv_sys->tasks);
+
+ /* Init the server concurrency restriction data structures */
+
+ os_fast_mutex_init(&srv_conc_mutex);
+
+ UT_LIST_INIT(srv_conc_queue);
+
+ for (i = 0; i < OS_THREAD_MAX_N; i++) {
+ conc_slot = srv_conc_slots + i;
+ conc_slot->reserved = FALSE;
+ conc_slot->event = os_event_create(NULL);
+ ut_a(conc_slot->event);
+ }
}
/*************************************************************************
@@ -1572,6 +1629,140 @@ srv_general_init(void)
}
/*************************************************************************
+Puts an OS thread to wait if there are too many concurrent threads
+(>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */
+
+void
+srv_conc_enter_innodb(
+/*==================*/
+ trx_t* trx) /* in: transaction object associated with the
+ thread */
+{
+ srv_conc_slot_t* slot;
+ ulint i;
+
+ os_fast_mutex_lock(&srv_conc_mutex);
+
+ if (srv_conc_n_threads < srv_thread_concurrency) {
+ srv_conc_n_threads++;
+
+ os_fast_mutex_unlock(&srv_conc_mutex);
+
+ return;
+ }
+
+ /* Too many threads inside: put to the current thread to a queue */
+
+ for (i = 0; i < OS_THREAD_MAX_N; i++) {
+ slot = srv_conc_slots + i;
+
+ if (!slot->reserved) {
+ break;
+ }
+ }
+
+ if (i == OS_THREAD_MAX_N) {
+ /* Could not find a free wait slot, we must let the
+ thread enter */
+
+ srv_conc_n_threads++;
+
+ os_fast_mutex_unlock(&srv_conc_mutex);
+
+ return;
+ }
+
+ /* Release possible search system latch this thread has */
+ if (trx->has_search_latch) {
+ trx_search_latch_release_if_reserved(trx);
+ }
+
+ /* Add to the queue */
+ slot->reserved = TRUE;
+ slot->wait_ended = FALSE;
+
+ UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot);
+
+ os_event_reset(slot->event);
+
+ os_fast_mutex_unlock(&srv_conc_mutex);
+
+ /* Go to wait for the event; when a thread leaves InnoDB it will
+ release this thread */
+
+ os_event_wait(slot->event);
+
+ os_fast_mutex_lock(&srv_conc_mutex);
+
+ /* NOTE that the thread which released this thread already
+ incremented the thread counter on behalf of this thread */
+
+ slot->reserved = FALSE;
+
+ UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot);
+
+ os_fast_mutex_unlock(&srv_conc_mutex);
+}
+
+/*************************************************************************
+This lets a thread enter InnoDB regardless of the number of threads inside
+InnoDB. This must be called when a thread ends a lock wait. */
+
+void
+srv_conc_force_enter_innodb(void)
+/*=============================*/
+{
+ os_fast_mutex_lock(&srv_conc_mutex);
+
+ srv_conc_n_threads++;
+
+ os_fast_mutex_unlock(&srv_conc_mutex);
+}
+
+/*************************************************************************
+This must be called when a thread exits InnoDB. This must also be called
+when a thread goes to wait for a lock. */
+
+void
+srv_conc_exit_innodb(void)
+/*======================*/
+{
+ srv_conc_slot_t* slot = NULL;
+
+ os_fast_mutex_lock(&srv_conc_mutex);
+
+ ut_a(srv_conc_n_threads > 0);
+
+ srv_conc_n_threads--;
+
+ if (srv_conc_n_threads < srv_thread_concurrency) {
+ /* Look for a slot where a thread is waiting and no other
+ thread has yet released the thread */
+
+ slot = UT_LIST_GET_FIRST(srv_conc_queue);
+
+ while (slot && slot->wait_ended == TRUE) {
+ slot = UT_LIST_GET_NEXT(srv_conc_queue, slot);
+ }
+
+ if (slot != NULL) {
+ slot->wait_ended = TRUE;
+
+ /* We increment the count on behalf of the released
+ thread */
+
+ srv_conc_n_threads++;
+ }
+ }
+
+ os_fast_mutex_unlock(&srv_conc_mutex);
+
+ if (slot != NULL) {
+ os_event_set(slot->event);
+ }
+}
+
+/*************************************************************************
Normalizes init parameter values to use units we use inside InnoDB. */
static
ulint
@@ -1713,10 +1904,20 @@ srv_suspend_mysql_thread(
mutex_exit(&kernel_mutex);
+ /* We must declare this OS thread to exit InnoDB, since a possible
+ other thread holding a lock which this thread waits for must be
+ allowed to enter, sooner or later */
+
+ srv_conc_exit_innodb();
+
/* Wait for the release */
os_event_wait(event);
+ /* Return back inside InnoDB */
+
+ srv_conc_force_enter_innodb();
+
mutex_enter(&kernel_mutex);
/* Release the slot for others to use */
@@ -1792,6 +1993,8 @@ srv_lock_timeout_and_monitor_thread(
UT_NOT_USED(arg);
last_monitor_time = time(NULL);
loop:
+ srv_lock_timeout_and_monitor_active = TRUE;
+
/* When someone is waiting for a lock, we wake up every second
and check if a timeout has passed for a lock wait */
@@ -1809,9 +2012,9 @@ loop:
if (time_elapsed > 15) {
- last_monitor_time = time(NULL);
-
if (srv_print_innodb_monitor) {
+
+ last_monitor_time = time(NULL);
printf("=====================================\n");
ut_print_timestamp(stdout);
@@ -1849,8 +2052,9 @@ loop:
printf("--------------\n"
"ROW OPERATIONS\n"
"--------------\n");
- printf("InnoDB main thread state: %s\n",
- srv_main_thread_op_info);
+ printf(
+ "%lu queries inside InnoDB; main thread: %s\n",
+ srv_conc_n_threads, srv_main_thread_op_info);
printf(
"Number of rows inserted %lu, updated %lu, deleted %lu, read %lu\n",
srv_n_rows_inserted,
@@ -1934,7 +2138,7 @@ loop:
(wait_time > (double) srv_lock_wait_timeout
|| wait_time < 0)) {
- /* Timeout exceeded or a wrap over in system
+ /* Timeout exceeded or a wrap-around in system
time counter: cancel the lock request queued
by the transaction and release possible
other transactions waiting behind */
@@ -1949,6 +2153,10 @@ loop:
mutex_exit(&kernel_mutex);
+ if (srv_shutdown_state >= SRV_SHUTDOWN_CLEANUP) {
+ goto exit_func;
+ }
+
if (some_waits || srv_print_innodb_monitor
|| srv_print_innodb_lock_monitor
|| srv_print_innodb_tablespace_monitor
@@ -1958,11 +2166,16 @@ loop:
/* No one was waiting for a lock and no monitor was active:
suspend this thread */
-
+
+ srv_lock_timeout_and_monitor_active = FALSE;
+
os_event_wait(srv_lock_timeout_thread_event);
goto loop;
+exit_func:
+ srv_lock_timeout_and_monitor_active = FALSE;
+
#ifndef __WIN__
return(NULL);
#else
@@ -1987,11 +2200,18 @@ srv_error_monitor_thread(
{
UT_NOT_USED(arg);
loop:
+ srv_error_monitor_active = TRUE;
+
os_thread_sleep(10000000);
sync_array_print_long_waits();
- goto loop;
+ if (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE) {
+
+ goto loop;
+ }
+
+ srv_error_monitor_active = FALSE;
#ifndef __WIN__
return(NULL);
@@ -2079,13 +2299,12 @@ loop:
for (i = 0; i < 10; i++) {
n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
-
srv_main_thread_op_info = "sleeping";
os_thread_sleep(1000000);
if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
- goto loop;
+ goto suspend_thread;
}
/* We flush the log once in a second even if no commit
@@ -2112,6 +2331,11 @@ loop:
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
}
+ if (srv_fast_shutdown && srv_shutdown_state > 0) {
+
+ goto background_loop;
+ }
+
if (srv_activity_count == old_activity_count) {
if (srv_print_thread_releases) {
@@ -2160,6 +2384,11 @@ loop:
while (n_pages_purged) {
+ if (srv_fast_shutdown && srv_shutdown_state > 0) {
+
+ goto background_loop;
+ }
+
srv_main_thread_op_info = "purging";
n_pages_purged = trx_purge();
@@ -2247,7 +2476,12 @@ background_loop:
log_archive_do(FALSE, &n_bytes_archived);
- if (n_pages_purged + n_bytes_merged + n_pages_flushed
+ if (srv_fast_shutdown && srv_shutdown_state > 0) {
+ if (n_pages_flushed + n_bytes_archived != 0) {
+
+ goto background_loop;
+ }
+ } else if (n_pages_purged + n_bytes_merged + n_pages_flushed
+ n_bytes_archived != 0) {
goto background_loop;
}
@@ -2261,6 +2495,7 @@ background_loop:
/* There is no work for background operations either: suspend
master thread to wait for more server activity */
+suspend_thread:
srv_main_thread_op_info = "suspending";
mutex_enter(&kernel_mutex);