diff options
author | unknown <monty@hundin.mysql.fi> | 2001-11-04 16:14:09 +0200 |
---|---|---|
committer | unknown <monty@hundin.mysql.fi> | 2001-11-04 16:14:09 +0200 |
commit | 0d1ba873aa11ea581ebbda9f450027329f2e1a3b (patch) | |
tree | 689c9d0271e23431f1ab0ac09e1af4d68a58ca76 /innobase/srv/srv0srv.c | |
parent | 9f90ff3f12f1fc2bcb70cde74dbd6f27e33e230c (diff) | |
parent | 0176dacd54b7eb62ebc4a81909b189517aee2cb4 (diff) | |
download | mariadb-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.c | 263 |
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); |