diff options
author | unknown <monty@donna.mysql.fi> | 2001-10-30 17:38:44 +0200 |
---|---|---|
committer | unknown <monty@donna.mysql.fi> | 2001-10-30 17:38:44 +0200 |
commit | 7b24c57c56b150132f0c4b541ef23a20f8f74ace (patch) | |
tree | 097886eb981160413975cb915243d4ae60718154 /innobase/srv | |
parent | fed395c75224ee11c1cd53fc24285e8575c6bec8 (diff) | |
download | mariadb-git-7b24c57c56b150132f0c4b541ef23a20f8f74ace.tar.gz |
Merge
include/my_base.h:
Try again merge InnoDB-3.23.44
include/mysqld_error.h:
Try again merge InnoDB-3.23.44
sql/handler.cc:
Try again merge InnoDB-3.23.44
sql/mysqld.cc:
Try again merge InnoDB-3.23.44
sql/ha_innobase.cc:
Try again merge InnoDB-3.23.44
sql/ha_innobase.h:
Try again merge InnoDB-3.23.44
sql/share/czech/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/danish/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/dutch/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/english/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/estonian/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/french/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/german/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/greek/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/hungarian/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/italian/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/japanese/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/korean/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/norwegian-ny/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/norwegian/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/polish/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/portuguese/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/romanian/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/russian/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/slovak/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/spanish/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/swedish/errmsg.txt:
Try again merge InnoDB-3.23.44
sql/share/ukrainian/errmsg.txt:
Try again merge InnoDB-3.23.44
innobase/btr/btr0btr.c:
Try again merge InnoDB-3.23.44
innobase/buf/buf0flu.c:
Try again merge InnoDB-3.23.44
innobase/buf/buf0lru.c:
Try again merge InnoDB-3.23.44
innobase/dict/dict0boot.c:
Try again merge InnoDB-3.23.44
innobase/dict/dict0crea.c:
Try again merge InnoDB-3.23.44
innobase/dict/dict0dict.c:
Try again merge InnoDB-3.23.44
innobase/ibuf/ibuf0ibuf.c:
Try again merge InnoDB-3.23.44
innobase/include/dict0boot.h:
Try again merge InnoDB-3.23.44
innobase/include/dict0boot.ic:
Try again merge InnoDB-3.23.44
innobase/include/dict0dict.h:
Try again merge InnoDB-3.23.44
innobase/include/os0file.h:
Try again merge InnoDB-3.23.44
innobase/include/os0sync.h:
Try again merge InnoDB-3.23.44
innobase/include/page0page.ic:
Try again merge InnoDB-3.23.44
innobase/include/read0read.h:
Try again merge InnoDB-3.23.44
innobase/include/row0mysql.h:
Try again merge InnoDB-3.23.44
innobase/include/srv0srv.h:
Try again merge InnoDB-3.23.44
innobase/include/srv0start.h:
Try again merge InnoDB-3.23.44
innobase/include/trx0purge.h:
Try again merge InnoDB-3.23.44
innobase/include/trx0rec.h:
Try again merge InnoDB-3.23.44
innobase/include/trx0trx.h:
Try again merge InnoDB-3.23.44
innobase/lock/lock0lock.c:
Try again merge InnoDB-3.23.44
innobase/log/log0log.c:
Try again merge InnoDB-3.23.44
innobase/log/log0recv.c:
Try again merge InnoDB-3.23.44
innobase/os/os0file.c:
Try again merge InnoDB-3.23.44
innobase/page/page0page.c:
Try again merge InnoDB-3.23.44
innobase/read/read0read.c:
Try again merge InnoDB-3.23.44
innobase/rem/rem0cmp.c:
Try again merge InnoDB-3.23.44
innobase/rem/rem0rec.c:
Try again merge InnoDB-3.23.44
innobase/row/row0ins.c:
Try again merge InnoDB-3.23.44
innobase/row/row0mysql.c:
Try again merge InnoDB-3.23.44
innobase/row/row0purge.c:
Try again merge InnoDB-3.23.44
innobase/row/row0row.c:
Try again merge InnoDB-3.23.44
innobase/row/row0sel.c:
Try again merge InnoDB-3.23.44
innobase/row/row0umod.c:
Try again merge InnoDB-3.23.44
innobase/row/row0upd.c:
Try again merge InnoDB-3.23.44
innobase/row/row0vers.c:
Try again merge InnoDB-3.23.44
innobase/srv/srv0start.c:
Try again merge InnoDB-3.23.44
innobase/sync/sync0arr.c:
Try again merge InnoDB-3.23.44
innobase/trx/trx0purge.c:
Try again merge InnoDB-3.23.44
innobase/trx/trx0rec.c:
Try again merge InnoDB-3.23.44
innobase/trx/trx0roll.c:
Try again merge InnoDB-3.23.44
innobase/trx/trx0sys.c:
Try again merge InnoDB-3.23.44
innobase/trx/trx0trx.c:
Try again merge InnoDB-3.23.44
innobase/trx/trx0undo.c:
Try again merge InnoDB-3.23.44
innobase/srv/srv0srv.c:
Commit change made by heikki
BitKeeper/etc/logging_ok:
Logging to logging@openlogging.org accepted
Diffstat (limited to 'innobase/srv')
-rw-r--r-- | innobase/srv/srv0srv.c | 261 | ||||
-rw-r--r-- | innobase/srv/srv0start.c | 94 |
2 files changed, 321 insertions, 34 deletions
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index eda96091279..87e36839599 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -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; @@ -1506,8 +1549,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)); @@ -1550,6 +1594,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); + } } /************************************************************************* @@ -1566,6 +1623,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 @@ -1707,10 +1898,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 */ @@ -1786,6 +1987,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 */ @@ -1803,9 +2006,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); @@ -1843,8 +2046,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, @@ -1928,7 +2132,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 */ @@ -1943,6 +2147,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 @@ -1952,11 +2160,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 @@ -1981,11 +2194,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); @@ -2073,13 +2293,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 @@ -2106,6 +2325,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) { @@ -2154,6 +2378,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(); @@ -2241,7 +2470,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; } @@ -2255,6 +2489,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); diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index b9e7050d546..c42c4ecf8fe 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -60,6 +60,10 @@ ibool srv_startup_is_before_trx_rollback_phase = FALSE; ibool srv_is_being_started = FALSE; ibool srv_was_started = FALSE; +/* At a shutdown the value first climbs to SRV_SHUTDOWN_CLEANUP +and then to SRV_SHUTDOWN_LAST_PHASE */ +ulint srv_shutdown_state = 0; + ibool measure_cont = FALSE; os_file_t files[1000]; @@ -175,6 +179,34 @@ srv_add_path_separator_if_needed( } /************************************************************************* +Calculates the low 32 bits when a file size which is given as a number +database pages is converted to the number of bytes. */ +static +ulint +srv_calc_low32( +/*===========*/ + /* out: low 32 bytes of file size when + expressed in bytes */ + ulint file_size) /* in: file size in database pages */ +{ + return(0xFFFFFFFF & (file_size << UNIV_PAGE_SIZE_SHIFT)); +} + +/************************************************************************* +Calculates the high 32 bits when a file size which is given as a number +database pages is converted to the number of bytes. */ +static +ulint +srv_calc_high32( +/*============*/ + /* out: high 32 bytes of file size when + expressed in bytes */ + ulint file_size) /* in: file size in database pages */ +{ + return(file_size >> (32 - UNIV_PAGE_SIZE_SHIFT)); +} + +/************************************************************************* Creates or opens the log files. */ static ulint @@ -214,8 +246,7 @@ open_or_create_log_file( return(DB_ERROR); } - files[i] = os_file_create( - name, OS_FILE_OPEN, OS_FILE_AIO, + files[i] = os_file_create(name, OS_FILE_OPEN, OS_FILE_AIO, OS_LOG_FILE, &ret); if (!ret) { fprintf(stderr, @@ -227,8 +258,9 @@ open_or_create_log_file( ret = os_file_get_size(files[i], &size, &size_high); ut_a(ret); - if (size != UNIV_PAGE_SIZE * srv_log_file_size - || size_high != 0) { + if (size != srv_calc_low32(srv_log_file_size) + || size_high != srv_calc_high32(srv_log_file_size)) { + fprintf(stderr, "InnoDB: Error: log file %s is of different size\n" "InnoDB: than specified in the .cnf file!\n", name); @@ -241,11 +273,13 @@ open_or_create_log_file( fprintf(stderr, "InnoDB: Log file %s did not exist: new to be created\n", name); - fprintf(stderr, "InnoDB: Setting log file %s size to %lu\n", - name, UNIV_PAGE_SIZE * srv_log_file_size); + fprintf(stderr, "InnoDB: Setting log file %s size to %lu MB\n", + name, srv_log_file_size + >> (20 - UNIV_PAGE_SIZE_SHIFT)); ret = os_file_set_size(name, files[i], - UNIV_PAGE_SIZE * srv_log_file_size, 0); + srv_calc_low32(srv_log_file_size), + srv_calc_high32(srv_log_file_size)); if (!ret) { fprintf(stderr, "InnoDB: Error in creating %s: probably out of disk space\n", @@ -277,8 +311,7 @@ open_or_create_log_file( if (k == 0 && i == 0) { arch_space_id = 2 * k + 1 + SRV_LOG_SPACE_FIRST_ID; - fil_space_create("arch_log_space", arch_space_id, - FIL_LOG); + fil_space_create("arch_log_space", arch_space_id, FIL_LOG); } else { arch_space_id = ULINT_UNDEFINED; } @@ -396,9 +429,14 @@ open_or_create_data_files( &size_high); ut_a(ret); - if (size != - UNIV_PAGE_SIZE * srv_data_file_sizes[i] - || size_high != 0) { + /* File sizes in srv_... are given in + database pages */ + + if (size != srv_calc_low32( + srv_data_file_sizes[i]) + || size_high != srv_calc_high32( + srv_data_file_sizes[i])) { + fprintf(stderr, "InnoDB: Error: data file %s is of different size\n" "InnoDB: than specified in the .cnf file!\n", name); @@ -426,14 +464,17 @@ open_or_create_data_files( *create_new_db = TRUE; } - fprintf(stderr, "InnoDB: Setting file %s size to %lu\n", - name, UNIV_PAGE_SIZE * srv_data_file_sizes[i]); + fprintf(stderr, + "InnoDB: Setting file %s size to %lu MB\n", + name, (srv_data_file_sizes[i] + >> (20 - UNIV_PAGE_SIZE_SHIFT))); fprintf(stderr, "InnoDB: Database physically writes the file full: wait...\n"); ret = os_file_set_size(name, files[i], - UNIV_PAGE_SIZE * srv_data_file_sizes[i], 0); + srv_calc_low32(srv_data_file_sizes[i]), + srv_calc_high32(srv_data_file_sizes[i])); if (!ret) { fprintf(stderr, @@ -673,16 +714,28 @@ innobase_start_or_create_for_mysql(void) return(DB_ERROR); } - sum_of_new_sizes = 0; + if (sizeof(ulint) == 4 + && srv_n_log_files * srv_log_file_size >= 262144) { + + fprintf(stderr, + "InnoDB: Error: combined size of log files must be < 4 GB\n" + "InnoDB: on 32-bit computers\n"); + return(DB_ERROR); + } + + sum_of_new_sizes = 0; + for (i = 0; i < srv_n_data_files; i++) { - if (srv_data_file_sizes[i] >= 262144) { +#ifndef __WIN__ + if (sizeof(off_t) < 5 && srv_data_file_sizes[i] >= 262144) { fprintf(stderr, - "InnoDB: Error: file size must be < 4 GB, or on some OS's < 2 GB\n"); + "InnoDB: Error: file size must be < 4 GB with this MySQL binary\n" + "InnoDB: and operating system combination, in some OS's < 2 GB\n"); return(DB_ERROR); } - +#endif sum_of_new_sizes += srv_data_file_sizes[i]; } @@ -889,7 +942,6 @@ innobase_start_or_create_for_mysql(void) /* Create the thread which warns of long semaphore waits */ os_thread_create(&srv_error_monitor_thread, NULL, thread_ids + 3 + SRV_MAX_N_IO_THREADS); - srv_was_started = TRUE; srv_is_being_started = FALSE; @@ -943,7 +995,7 @@ innobase_shutdown_for_mysql(void) the tablespace header(s), and copy all log data to archive */ logs_empty_and_mark_files_at_shutdown(); - + ut_free_all_mem(); return((int) DB_SUCCESS); |