summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <marko@hundin.mysql.fi>2004-10-27 13:33:11 +0300
committerunknown <marko@hundin.mysql.fi>2004-10-27 13:33:11 +0300
commit743597ea96cbf227c2c5dd34b9837802d62ad834 (patch)
tree811cd8122c4f67f06ae87f7dde570b7aea9d484d /innobase
parent9abe7d272bcd75ef4eb83a33f31a3c9b756317a1 (diff)
downloadmariadb-git-743597ea96cbf227c2c5dd34b9837802d62ad834.tar.gz
Backport innodb_max_purge_lag from 4.1
innobase/include/srv0srv.h: Add configuration parameter srv_max_purge_lag. Add global variable srv_dml_needed_delay. innobase/include/trx0sys.h: Add trx_sys->rseg_history_len innobase/row/row0mysql.c: Add row_mysql_delay_if_needed() for delaying INSERTs, UPDATEs and DELETEs for srv_dml_needed_delay microseconds. innobase/srv/srv0srv.c: Define global variable srv_dml_needed_delay. Define configuration parameter srv_max_purge_lag. innobase/trx/trx0purge.c: Update trx_sys->rseg_history_len. trx_purge(): Compute srv_dml_needed_delay from srv_max_purge_lag and trx_sys->rseg_history_len. innobase/trx/trx0rseg.c: Initialize trx_sys->rseg_history_len at InnoDB start-up. sql/ha_innodb.h: Add configuration parameter srv_max_purge_lag. sql/mysqld.cc: Add startup option innodb_max_purge_lag, with default value 0 (meaning infinite, disabling the feature). sql/set_var.cc: Add global variable innodb_max_purge_lag.
Diffstat (limited to 'innobase')
-rw-r--r--innobase/include/srv0srv.h2
-rw-r--r--innobase/include/trx0sys.h4
-rw-r--r--innobase/row/row0mysql.c17
-rw-r--r--innobase/srv/srv0srv.c6
-rw-r--r--innobase/trx/trx0purge.c38
-rw-r--r--innobase/trx/trx0rseg.c7
6 files changed, 73 insertions, 1 deletions
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 57ca1f84f26..c76a1917615 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -99,6 +99,7 @@ extern ibool srv_use_doublewrite_buf;
extern ibool srv_set_thread_priorities;
extern int srv_query_thread_priority;
+extern ulint srv_max_purge_lag;
/*-------------------------------------------*/
extern ulint srv_n_rows_inserted;
@@ -152,6 +153,7 @@ extern ulint srv_test_array_size;
extern ulint srv_activity_count;
extern ulint srv_fatal_semaphore_wait_threshold;
+extern ulint srv_dml_needed_delay;
extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
query threads, and lock table: we allocate
diff --git a/innobase/include/trx0sys.h b/innobase/include/trx0sys.h
index c7ef4d1929d..4d83c5eeaae 100644
--- a/innobase/include/trx0sys.h
+++ b/innobase/include/trx0sys.h
@@ -419,6 +419,10 @@ struct trx_sys_struct{
trx_rseg_t* rseg_array[TRX_SYS_N_RSEGS];
/* Pointer array to rollback segments;
NULL if slot not in use */
+ ulint rseg_history_len;/* Length of the TRX_RSEG_HISTORY
+ list (update undo logs for committed
+ transactions), protected by
+ rseg->mutex */
UT_LIST_BASE_NODE_T(read_view_t) view_list;
/* List of read views sorted on trx no,
biggest first */
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 3eb4f0de60e..78b2aa8e28f 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -89,6 +89,19 @@ row_mysql_is_system_table(
|| 0 == strcmp(name + 6, "user")
|| 0 == strcmp(name + 6, "db"));
}
+
+/***********************************************************************
+Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */
+static
+void
+row_mysql_delay_if_needed(void)
+/*===========================*/
+{
+ if (srv_dml_needed_delay) {
+ os_thread_sleep(srv_dml_needed_delay);
+ }
+}
+
/***********************************************************************
Reads a MySQL format variable-length field (like VARCHAR) length and
returns pointer to the field data. */
@@ -856,6 +869,8 @@ row_insert_for_mysql(
trx->op_info = (char *) "inserting";
+ row_mysql_delay_if_needed();
+
trx_start_if_not_started(trx);
if (node == NULL) {
@@ -1071,6 +1086,8 @@ row_update_for_mysql(
trx->op_info = (char *) "updating or deleting";
+ row_mysql_delay_if_needed();
+
trx_start_if_not_started(trx);
node = prebuilt->upd_node;
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 0643ab96c1d..0a814268a36 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -58,6 +58,10 @@ ulint srv_activity_count = 0;
/* The following is the maximum allowed duration of a lock wait. */
ulint srv_fatal_semaphore_wait_threshold = 600;
+/* How much data manipulation language (DML) statements need to be delayed,
+in microseconds, in order to reduce the lagging of the purge thread. */
+ulint srv_dml_needed_delay = 0;
+
ibool srv_lock_timeout_and_monitor_active = FALSE;
ibool srv_error_monitor_active = FALSE;
@@ -841,6 +845,8 @@ srv_general_init(void)
/*======================= InnoDB Server FIFO queue =======================*/
+/* Maximum allowable purge history length. <=0 means 'infinite'. */
+ulint srv_max_purge_lag = 0;
/*************************************************************************
Puts an OS thread to wait if there are too many concurrent threads
diff --git a/innobase/trx/trx0purge.c b/innobase/trx/trx0purge.c
index a8b6b9fcc21..d772af47b29 100644
--- a/innobase/trx/trx0purge.c
+++ b/innobase/trx/trx0purge.c
@@ -295,6 +295,9 @@ trx_purge_add_update_undo_to_history(
/* Add the log as the first in the history list */
flst_add_first(rseg_header + TRX_RSEG_HISTORY,
undo_header + TRX_UNDO_HISTORY_NODE, mtr);
+ mutex_enter(&kernel_mutex);
+ trx_sys->rseg_history_len++;
+ mutex_exit(&kernel_mutex);
/* Write the trx number to the undo log header */
mlog_write_dulint(undo_header + TRX_UNDO_TRX_NO, trx->no, mtr);
@@ -386,6 +389,12 @@ loop:
flst_cut_end(rseg_hdr + TRX_RSEG_HISTORY,
log_hdr + TRX_UNDO_HISTORY_NODE, n_removed_logs, &mtr);
+
+ mutex_enter(&kernel_mutex);
+ ut_ad(trx_sys->rseg_history_len >= n_removed_logs);
+ trx_sys->rseg_history_len -= n_removed_logs;
+ mutex_exit(&kernel_mutex);
+
freed = FALSE;
while (!freed) {
@@ -470,6 +479,11 @@ loop:
}
if (cmp >= 0) {
+ mutex_enter(&kernel_mutex);
+ ut_a(trx_sys->rseg_history_len >= n_removed_logs);
+ trx_sys->rseg_history_len -= n_removed_logs;
+ mutex_exit(&kernel_mutex);
+
flst_truncate_end(rseg_hdr + TRX_RSEG_HISTORY,
log_hdr + TRX_UNDO_HISTORY_NODE,
n_removed_logs, &mtr);
@@ -1031,6 +1045,30 @@ trx_purge(void)
purge_sys->view = NULL;
mem_heap_empty(purge_sys->heap);
+ /* Determine how much data manipulation language (DML) statements
+ need to be delayed in order to reduce the lagging of the purge
+ thread. */
+ srv_dml_needed_delay = 0; /* in microseconds; default: no delay */
+
+ /* If we cannot advance the 'purge view' because of an old
+ 'consistent read view', then the DML statements cannot be delayed.
+ Also, srv_max_purge_lag <= 0 means 'infinity'. */
+ if (srv_max_purge_lag > 0
+ && !UT_LIST_GET_LAST(trx_sys->view_list)) {
+ float ratio = (float) trx_sys->rseg_history_len
+ / srv_max_purge_lag;
+ if (ratio > ULINT_MAX / 10000) {
+ /* Avoid overflow: maximum delay is 4295 seconds */
+ srv_dml_needed_delay = ULINT_MAX;
+ } else if (ratio > 1) {
+ /* If the history list length exceeds the
+ innodb_max_purge_lag, the
+ data manipulation statements are delayed
+ by at least 5000 microseconds. */
+ srv_dml_needed_delay = (ulint) ((ratio - .5) * 10000);
+ }
+ }
+
purge_sys->view = read_view_oldest_copy_or_open_new(NULL,
purge_sys->heap);
mutex_exit(&kernel_mutex);
diff --git a/innobase/trx/trx0rseg.c b/innobase/trx/trx0rseg.c
index e3885c86def..a01d4bb835d 100644
--- a/innobase/trx/trx0rseg.c
+++ b/innobase/trx/trx0rseg.c
@@ -135,6 +135,7 @@ trx_rseg_mem_create(
trx_ulogf_t* undo_log_hdr;
fil_addr_t node_addr;
ulint sum_of_undo_sizes;
+ ulint len;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -166,7 +167,9 @@ trx_rseg_mem_create(
MLOG_4BYTES, mtr)
+ 1 + sum_of_undo_sizes;
- if (flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr) > 0) {
+ len = flst_get_len(rseg_header + TRX_RSEG_HISTORY, mtr);
+ if (len > 0) {
+ trx_sys->rseg_history_len += len;
node_addr = trx_purge_get_log_from_hist(
flst_get_last(rseg_header + TRX_RSEG_HISTORY,
@@ -206,6 +209,8 @@ trx_rseg_list_and_array_init(
UT_LIST_INIT(trx_sys->rseg_list);
+ trx_sys->rseg_history_len = 0;
+
for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);