summaryrefslogtreecommitdiff
path: root/innobase/srv
diff options
context:
space:
mode:
authormonty@narttu.mysql.fi <>2003-05-19 16:35:49 +0300
committermonty@narttu.mysql.fi <>2003-05-19 16:35:49 +0300
commitdd2b7918cdd5e0e643cff0305542ccd4aa8f1b6b (patch)
tree6025913cf3d482ba0783bf3420f7341c10cd574a /innobase/srv
parent524878e9358706ffb5908677c746a9060c66ad32 (diff)
parentfc0df599dc72408419e80a5f1d3e07dc5f0fec88 (diff)
downloadmariadb-git-dd2b7918cdd5e0e643cff0305542ccd4aa8f1b6b.tar.gz
Merge with 4.0.13
Diffstat (limited to 'innobase/srv')
-rw-r--r--innobase/srv/Makefile.am2
-rw-r--r--innobase/srv/srv0srv.c194
-rw-r--r--innobase/srv/srv0start.c42
3 files changed, 177 insertions, 61 deletions
diff --git a/innobase/srv/Makefile.am b/innobase/srv/Makefile.am
index b4bdeb7c03b..752683b82b8 100644
--- a/innobase/srv/Makefile.am
+++ b/innobase/srv/Makefile.am
@@ -17,7 +17,7 @@
include ../include/Makefile.i
-libs_LIBRARIES = libsrv.a
+noinst_LIBRARIES = libsrv.a
libsrv_a_SOURCES = srv0srv.c srv0que.c srv0start.c
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index af11516e9f0..7cd831fe239 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -162,6 +162,13 @@ char* srv_file_flush_method_str = NULL;
ulint srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
+/* The InnoDB main thread tries to keep the ratio of modified pages
+in the buffer pool to all database pages in the buffer pool smaller than
+the following number. But it is not guaranteed that the value stays below
+that during a time of heavy update/insert activity. */
+
+ulint srv_max_buf_pool_modified_pct = 90;
+
/* If the following is != 0 we do not allow inserts etc. This protects
the user from forgetting the innodb_force_recovery keyword to my.cnf */
@@ -1881,11 +1888,11 @@ retry:
/* Go to wait for the event; when a thread leaves InnoDB it will
release this thread */
- trx->op_info = "waiting in InnoDB queue";
+ trx->op_info = (char*)"waiting in InnoDB queue";
os_event_wait(slot->event);
- trx->op_info = "";
+ trx->op_info = (char*)"";
os_fast_mutex_lock(&srv_conc_mutex);
@@ -2368,12 +2375,35 @@ srv_sprintf_innodb_monitor(
buf = buf + strlen(buf);
ut_a(buf < buf_end + 1500);
- buf += sprintf(buf, "------------\n"
- "TRANSACTIONS\n"
- "------------\n");
+ if (*dict_foreign_err_buf != '\0') {
+ buf += sprintf(buf,
+ "------------------------\n"
+ "LATEST FOREIGN KEY ERROR\n"
+ "------------------------\n");
+
+ if (buf_end - buf > 6000) {
+ buf+= sprintf(buf, "%.4000s", dict_foreign_err_buf);
+ }
+ }
+
+ ut_a(buf < buf_end + 1500);
+
+ if (*dict_unique_err_buf != '\0') {
+ buf += sprintf(buf,
+"---------------------------------------------------------------\n"
+"LATEST UNIQUE KEY ERROR (is masked in REPLACE or INSERT IGNORE)\n"
+"---------------------------------------------------------------\n");
+
+ if (buf_end - buf > 6000) {
+ buf+= sprintf(buf, "%.4000s", dict_unique_err_buf);
+ }
+ }
+
+ ut_a(buf < buf_end + 1500);
+
lock_print_info(buf, buf_end);
buf = buf + strlen(buf);
-
+
buf += sprintf(buf, "--------\n"
"FILE I/O\n"
"--------\n");
@@ -2777,6 +2807,7 @@ srv_master_thread(
ulint n_ios_old;
ulint n_ios_very_old;
ulint n_pend_ios;
+ ibool skip_sleep = FALSE;
ulint i;
UT_NOT_USED(arg);
@@ -2794,24 +2825,42 @@ srv_master_thread(
os_event_set(srv_sys->operational);
loop:
+ /*****************************************************************/
+ /* ---- When there is database activity by users, we cycle in this
+ loop */
+
srv_main_thread_op_info = (char*) "reserving kernel mutex";
n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
mutex_enter(&kernel_mutex);
+ /* Store the user activity counter at the start of this loop */
old_activity_count = srv_activity_count;
mutex_exit(&kernel_mutex);
- /* We run purge and a batch of ibuf_contract every 10 seconds, even
- if the server were active: */
+ if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
+
+ goto suspend_thread;
+ }
+
+ /* ---- We run the following loop approximately once per second
+ when there is database activity */
+
+ skip_sleep = FALSE;
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 = (char*)"sleeping";
- os_thread_sleep(1000000);
+
+ if (!skip_sleep) {
+
+ os_thread_sleep(1000000);
+ }
+
+ skip_sleep = FALSE;
/* ALTER TABLE in MySQL requires on Unix that the table handler
can drop tables lazily after there no longer are SELECT
@@ -2824,9 +2873,9 @@ loop:
srv_main_thread_op_info = (char*)"";
- if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
+ if (srv_fast_shutdown && srv_shutdown_state > 0) {
- goto suspend_thread;
+ goto background_loop;
}
/* We flush the log once in a second even if no commit
@@ -2834,10 +2883,9 @@ loop:
at transaction commit */
srv_main_thread_op_info = (char*)"flushing log";
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
- log_flush_to_disk();
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
- /* If there were less than 10 i/os during the
+ /* If there were less than 5 i/os during the
one second sleep, we assume that there is free
disk i/o capacity available, and it makes sense to
do an insert buffer merge. */
@@ -2846,35 +2894,45 @@ loop:
+ log_sys->n_pending_writes;
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
- if (n_pend_ios < 3 && (n_ios - n_ios_old < 10)) {
+ if (n_pend_ios < 3 && (n_ios - n_ios_old < 5)) {
srv_main_thread_op_info =
(char*)"doing insert buffer merge";
ibuf_contract_for_n_pages(TRUE, 5);
srv_main_thread_op_info =
(char*)"flushing log";
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
- log_flush_to_disk();
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP,
+ TRUE);
}
-
- if (srv_fast_shutdown && srv_shutdown_state > 0) {
- goto background_loop;
+ if (buf_get_modified_ratio_pct() >
+ srv_max_buf_pool_modified_pct) {
+
+ /* Try to keep the number of modified pages in the
+ buffer pool under the limit wished by the user */
+
+ n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
+ ut_dulint_max);
+
+ /* If we had to do the flush, it may have taken
+ even more than 1 second, and also, there may be more
+ to flush. Do not sleep 1 second during the next
+ iteration of this loop. */
+
+ skip_sleep = TRUE;
}
if (srv_activity_count == old_activity_count) {
- if (srv_print_thread_releases) {
- printf("Master thread wakes up!\n");
- }
+ /* There is no user activity at the moment, go to
+ the background loop */
goto background_loop;
}
}
- if (srv_print_thread_releases) {
- printf("Master thread wakes up!\n");
- }
+ /* ---- We perform the following code approximately once per
+ 10 seconds when there is database activity */
#ifdef MEM_PERIODIC_CHECK
/* Check magic numbers of every allocated mem block once in 10
@@ -2883,7 +2941,7 @@ loop:
#endif
/* If there were less than 200 i/os during the 10 second period,
we assume that there is free disk i/o capacity available, and it
- makes sense to do a buffer pool flush. */
+ makes sense to flush 100 pages. */
n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
@@ -2891,11 +2949,10 @@ loop:
if (n_pend_ios < 3 && (n_ios - n_ios_very_old < 200)) {
srv_main_thread_op_info = (char*) "flushing buffer pool pages";
- buf_flush_batch(BUF_FLUSH_LIST, 50, ut_dulint_max);
+ buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
srv_main_thread_op_info = (char*) "flushing log";
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
- log_flush_to_disk();
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
}
/* We run a batch of insert buffer merge every 10 seconds,
@@ -2905,8 +2962,7 @@ loop:
ibuf_contract_for_n_pages(TRUE, 5);
srv_main_thread_op_info = (char*)"flushing log";
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
- log_flush_to_disk();
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
/* We run a full purge every 10 seconds, even if the server
were active */
@@ -2930,27 +2986,32 @@ loop:
if (difftime(current_time, last_flush_time) > 1) {
srv_main_thread_op_info = (char*) "flushing log";
- log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
- log_flush_to_disk();
+ log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP,
+ TRUE);
last_flush_time = current_time;
}
}
+
+ srv_main_thread_op_info = (char*)"flushing buffer pool pages";
-background_loop:
- /* In this loop we run background operations when the server
- is quiet and we also come here about once in 10 seconds */
+ /* Flush a few oldest pages to make a new checkpoint younger */
- srv_main_thread_op_info = (char*)"doing background drop tables";
+ if (buf_get_modified_ratio_pct() > 70) {
- n_tables_to_drop = row_drop_tables_for_mysql_in_background();
+ /* If there are lots of modified pages in the buffer pool
+ (> 70 %), we assume we can afford reserving the disk(s) for
+ the time it requires to flush 100 pages */
- srv_main_thread_op_info = (char*)"";
-
- srv_main_thread_op_info = (char*)"flushing buffer pool pages";
-
- /* Flush a few oldest pages to make the checkpoint younger */
+ n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
+ ut_dulint_max);
+ } else {
+ /* Otherwise, we only flush a small number of pages so that
+ we do not unnecessarily use much disk i/o capacity from
+ other work */
- n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10, ut_dulint_max);
+ n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10,
+ ut_dulint_max);
+ }
srv_main_thread_op_info = (char*)"making checkpoint";
@@ -2961,16 +3022,31 @@ background_loop:
srv_main_thread_op_info = (char*)"reserving kernel mutex";
mutex_enter(&kernel_mutex);
+
+ /* ---- When there is database activity, we jump from here back to
+ the start of loop */
+
if (srv_activity_count != old_activity_count) {
mutex_exit(&kernel_mutex);
goto loop;
}
- old_activity_count = srv_activity_count;
+
mutex_exit(&kernel_mutex);
+ /* If the database is quiet, we enter the background loop */
+
+ /*****************************************************************/
+background_loop:
+ /* ---- In this loop we run background operations when the server
+ is quiet from user activity */
+
/* The server has been quiet for a while: start running background
operations */
+ srv_main_thread_op_info = (char*)"doing background drop tables";
+
+ n_tables_to_drop = row_drop_tables_for_mysql_in_background();
+
srv_main_thread_op_info = (char*)"purging";
if (srv_fast_shutdown && srv_shutdown_state > 0) {
@@ -3005,6 +3081,7 @@ background_loop:
}
mutex_exit(&kernel_mutex);
+flush_loop:
srv_main_thread_op_info = (char*)"flushing buffer pool pages";
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
@@ -3017,13 +3094,22 @@ background_loop:
}
mutex_exit(&kernel_mutex);
- srv_main_thread_op_info = (char*) "waiting for buffer pool flush to end";
+ srv_main_thread_op_info =
+ (char*) "waiting for buffer pool flush to end";
buf_flush_wait_batch_end(BUF_FLUSH_LIST);
srv_main_thread_op_info = (char*)"making checkpoint";
log_checkpoint(TRUE, FALSE);
+ if (buf_get_modified_ratio_pct() > srv_max_buf_pool_modified_pct) {
+
+ /* Try to keep the number of modified pages in the
+ buffer pool under the limit wished by the user */
+
+ goto flush_loop;
+ }
+
srv_main_thread_op_info = (char*)"reserving kernel mutex";
mutex_enter(&kernel_mutex);
@@ -3038,15 +3124,24 @@ background_loop:
log_archive_do(FALSE, &n_bytes_archived);
+ /* Keep looping in the background loop if still work to do */
+
if (srv_fast_shutdown && srv_shutdown_state > 0) {
if (n_tables_to_drop + n_pages_flushed
+ n_bytes_archived != 0) {
+ /* If we are doing a fast shutdown (= the default)
+ we do not do purge or insert buffer merge. But we
+ flush the buffer pool completely to disk. */
+
goto background_loop;
}
} else if (n_tables_to_drop +
- n_pages_purged + n_bytes_merged + n_pages_flushed
+ n_pages_purged + n_bytes_merged + n_pages_flushed
+ n_bytes_archived != 0) {
+ /* In a 'slow' shutdown we run purge and the insert buffer
+ merge to completion */
+
goto background_loop;
}
@@ -3078,6 +3173,9 @@ suspend_thread:
os_event_wait(event);
+ /* When there is user activity, InnoDB will set the event and the main
+ thread goes back to loop: */
+
goto loop;
#ifndef __WIN__
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 33d4a30e227..536aa5b67e4 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -161,13 +161,13 @@ srv_parse_data_file_paths_and_sizes(
}
if (strlen(str) >= ut_strlen(":autoextend")
- && 0 == ut_memcmp(str, ":autoextend",
+ && 0 == ut_memcmp(str, (char*)":autoextend",
ut_strlen(":autoextend"))) {
str += ut_strlen(":autoextend");
if (strlen(str) >= ut_strlen(":max:")
- && 0 == ut_memcmp(str, ":max:",
+ && 0 == ut_memcmp(str, (char*)":max:",
ut_strlen(":max:"))) {
str += ut_strlen(":max:");
@@ -265,7 +265,7 @@ srv_parse_data_file_paths_and_sizes(
(*data_file_sizes)[i] = size;
if (strlen(str) >= ut_strlen(":autoextend")
- && 0 == ut_memcmp(str, ":autoextend",
+ && 0 == ut_memcmp(str, (char*)":autoextend",
ut_strlen(":autoextend"))) {
*is_auto_extending = TRUE;
@@ -273,7 +273,7 @@ srv_parse_data_file_paths_and_sizes(
str += ut_strlen(":autoextend");
if (strlen(str) >= ut_strlen(":max:")
- && 0 == ut_memcmp(str, ":max:",
+ && 0 == ut_memcmp(str, (char*)":max:",
ut_strlen(":max:"))) {
str += ut_strlen(":max:");
@@ -864,6 +864,7 @@ open_or_create_data_files(
return(DB_SUCCESS);
}
+#ifdef notdefined
/*********************************************************************
This thread is used to measure contention of latches. */
static
@@ -935,6 +936,7 @@ test_measure_cont(
return(0);
}
+#endif
/********************************************************************
Starts InnoDB and creates a new database if database files
@@ -1053,20 +1055,24 @@ innobase_start_or_create_for_mysql(void)
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
#ifndef __WIN__
- } else if (0 == ut_strcmp(srv_file_flush_method_str, "fdatasync")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str,
+ (char*)"fdatasync")) {
srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
- } else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str,
+ (char*)"O_DSYNC")) {
srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
} else if (0 == ut_strcmp(srv_file_flush_method_str,
- "littlesync")) {
+ (char*)"littlesync")) {
srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
- } else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str,
+ (char*)"nosync")) {
srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
#else
- } else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
+ } else if (0 == ut_strcmp(srv_file_flush_method_str,
+ (char*)"normal")) {
srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
os_aio_use_native_aio = FALSE;
@@ -1196,7 +1202,14 @@ innobase_start_or_create_for_mysql(void)
&max_flushed_lsn, &max_arch_log_no,
&sum_of_new_sizes);
if (err != DB_SUCCESS) {
- fprintf(stderr, "InnoDB: Could not open data files\n");
+ fprintf(stderr,
+"InnoDB: Could not open or create data files.\n"
+"InnoDB: If you tried to add new data files, and it failed here,\n"
+"InnoDB: you should now edit innodb_data_file_path in my.cnf back\n"
+"InnoDB: to what it was, and remove the new ibdata files InnoDB created\n"
+"InnoDB: in this failed attempt. InnoDB only wrote those files full of\n"
+"InnoDB: zeros, but did not yet use them in any way. But be careful: do not\n"
+"InnoDB: remove old data files which contain your precious data!\n");
return((int) err);
}
@@ -1207,7 +1220,10 @@ innobase_start_or_create_for_mysql(void)
and restore them from the doublewrite buffer if
possible */
- trx_sys_doublewrite_restore_corrupt_pages();
+ if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
+
+ trx_sys_doublewrite_restore_corrupt_pages();
+ }
}
srv_normalize_path_for_win(srv_arch_dir);
@@ -1478,7 +1494,9 @@ innobase_start_or_create_for_mysql(void)
fprintf(stderr,
"InnoDB: !!! innodb_force_recovery is set to %lu !!!\n",
srv_force_recovery);
- }
+ }
+
+ fflush(stderr);
return((int) DB_SUCCESS);
}