summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <heikki@hundin.mysql.fi>2003-07-03 21:25:55 +0300
committerunknown <heikki@hundin.mysql.fi>2003-07-03 21:25:55 +0300
commit5dc1e4b98ac6223b9854f26fd689d7e68897e3c9 (patch)
tree4bae1e813c986da0cdde9b78f41247a806c985d0
parentdb5283b30667c9d427228069314f53d38c4ef8f1 (diff)
downloadmariadb-git-5dc1e4b98ac6223b9854f26fd689d7e68897e3c9.tar.gz
Many files:
Remove potential starvation of a full log buffer flush: only flush up to the lsn which was the largest at the time when we requested the full log buffer flush os0sync.h, os0sync.c: Fix a bug in os_event on Unix: even though we signaled the event, some threads could continue waiting if the event became nonsignaled quickly again; this made group commit less efficient than it should be innobase/os/os0sync.c: Fix a bug in os_event on Unix: even though we signaled the event, some threads could continue waiting if the event became nonsignaled quickly again; this made group commit less efficient than it should be innobase/include/os0sync.h: Fix a bug in os_event on Unix: even though we signaled the event, some threads could continue waiting if the event became nonsignaled quickly again; this made group commit less efficient than it should be innobase/log/log0log.c: Remove potential starvation of a full log buffer flush: only flush up to the lsn which was the largest at the time when we requested the full log buffer flush innobase/include/log0log.h: Remove potential starvation of a full log buffer flush: only flush up to the lsn which was the largest at the time when we requested the full log buffer flush innobase/srv/srv0srv.c: Remove potential starvation of a full log buffer flush: only flush up to the lsn which was the largest at the time when we requested the full log buffer flush innobase/row/row0mysql.c: Remove potential starvation of a full log buffer flush: only flush up to the lsn which was the largest at the time when we requested the full log buffer flush innobase/trx/trx0trx.c: Remove potential starvation of a full log buffer flush: only flush up to the lsn which was the largest at the time when we requested the full log buffer flush sql/ha_innodb.cc: Remove potential starvation of a full log buffer flush: only flush up to the lsn which was the largest at the time when we requested the full log buffer flush innobase/btr/btr0btr.c: Remove potential starvation of a full log buffer flush: only flush up to the lsn which was the largest at the time when we requested the full log buffer flush
-rw-r--r--innobase/btr/btr0btr.c29
-rw-r--r--innobase/include/log0log.h6
-rw-r--r--innobase/include/os0sync.h8
-rw-r--r--innobase/log/log0log.c25
-rw-r--r--innobase/os/os0sync.c15
-rw-r--r--innobase/row/row0mysql.c2
-rw-r--r--innobase/srv/srv0srv.c20
-rw-r--r--innobase/trx/trx0trx.c4
-rw-r--r--sql/ha_innodb.cc10
9 files changed, 97 insertions, 22 deletions
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c
index 51c164b7cef..d8a0959e47f 100644
--- a/innobase/btr/btr0btr.c
+++ b/innobase/btr/btr0btr.c
@@ -822,9 +822,16 @@ btr_page_reorganize_low(
{
page_t* new_page;
ulint log_mode;
+ ulint data_size1;
+ ulint data_size2;
+ ulint max_ins_size1;
+ ulint max_ins_size2;
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
+ data_size1 = page_get_data_size(page);
+ max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1);
+
/* Write the log record */
mlog_write_initial_log_record(page, MLOG_PAGE_REORGANIZE, mtr);
@@ -859,6 +866,19 @@ btr_page_reorganize_low(
lock_move_reorganize_page(page, new_page);
}
+ data_size2 = page_get_data_size(page);
+ max_ins_size2 = page_get_max_insert_size_after_reorganize(page, 1);
+
+ if (data_size1 != data_size2 || max_ins_size1 != max_ins_size2) {
+ buf_page_print(page);
+ buf_page_print(new_page);
+ fprintf(stderr,
+"InnoDB: Error: page old data size %lu new data size %lu\n"
+"InnoDB: Error: page old max ins size %lu new max ins size %lu\n"
+"InnoDB: Make a detailed bug report and send it to mysql@lists.mysql.com\n",
+ data_size1, data_size2, max_ins_size1, max_ins_size2);
+ }
+
buf_frame_free(new_page);
/* Restore logging mode */
@@ -1945,11 +1965,20 @@ btr_compress(
btr_page_reorganize(merge_page, mtr);
+ max_ins_size = page_get_max_insert_size(merge_page, n_recs);
+
ut_ad(page_validate(merge_page, cursor->index));
ut_ad(page_get_max_insert_size(merge_page, n_recs)
== max_ins_size_reorg);
}
+ if (data_size > max_ins_size) {
+
+ /* Add fault tolerance, though this should never happen */
+
+ return;
+ }
+
btr_search_drop_page_hash_index(page);
/* Remove the page from the level list */
diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h
index 4e1404b15fe..e79e914e4f6 100644
--- a/innobase/include/log0log.h
+++ b/innobase/include/log0log.h
@@ -173,6 +173,12 @@ log_write_up_to(
/* in: TRUE if we want the written log also to be
flushed to disk */
/********************************************************************
+Does a syncronous flush of the log buffer to disk. */
+
+void
+log_buffer_flush_to_disk(void);
+/*==========================*/
+/********************************************************************
Advances the smallest lsn for which there are unflushed dirty blocks in the
buffer pool and also may make a new checkpoint. NOTE: this function may only
be called if the calling thread owns no synchronization objects! */
diff --git a/innobase/include/os0sync.h b/innobase/include/os0sync.h
index 634507467f9..e1cf263216e 100644
--- a/innobase/include/os0sync.h
+++ b/innobase/include/os0sync.h
@@ -36,8 +36,12 @@ typedef os_event_struct_t* os_event_t;
struct os_event_struct {
os_fast_mutex_t os_mutex; /* this mutex protects the next
fields */
- ibool is_set; /* this is TRUE if the next mutex is
- not reserved */
+ ibool is_set; /* this is TRUE when the event is
+ in the signaled state, i.e., a thread
+ does not stop if it tries to wait for
+ this event */
+ ib_longlong signal_count; /* this is incremented each time
+ the event becomes signaled */
pthread_cond_t cond_var; /* condition variable is used in
waiting for the event */
UT_LIST_NODE_T(os_event_struct_t) os_event_list;
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index b5ce1a3d97b..53ca97baaa0 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -178,7 +178,8 @@ loop:
/* Not enough free space, do a syncronous flush of the log
buffer */
- log_write_up_to(ut_dulint_max, LOG_WAIT_ALL_GROUPS, TRUE);
+
+ log_buffer_flush_to_disk();
count++;
@@ -1365,6 +1366,24 @@ do_waits:
}
/********************************************************************
+Does a syncronous flush of the log buffer to disk. */
+
+void
+log_buffer_flush_to_disk(void)
+/*==========================*/
+{
+ dulint lsn;
+
+ mutex_enter(&(log_sys->mutex));
+
+ lsn = log_sys->lsn;
+
+ mutex_exit(&(log_sys->mutex));
+
+ log_write_up_to(lsn, LOG_WAIT_ALL_GROUPS, TRUE);
+}
+
+/********************************************************************
Tries to establish a big enough margin of free space in the log buffer, such
that a new log entry can be catenated without an immediate need for a flush. */
static
@@ -1374,6 +1393,7 @@ log_flush_margin(void)
{
ibool do_flush = FALSE;
log_t* log = log_sys;
+ dulint lsn;
mutex_enter(&(log->mutex));
@@ -1384,13 +1404,14 @@ log_flush_margin(void)
free space */
} else {
do_flush = TRUE;
+ lsn = log->lsn;
}
}
mutex_exit(&(log->mutex));
if (do_flush) {
- log_write_up_to(ut_dulint_max, LOG_NO_WAIT, FALSE);
+ log_write_up_to(lsn, LOG_NO_WAIT, FALSE);
}
}
diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c
index bf5fc57bf57..827d68501db 100644
--- a/innobase/os/os0sync.c
+++ b/innobase/os/os0sync.c
@@ -143,6 +143,7 @@ os_event_create(
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
#endif
event->is_set = FALSE;
+ event->signal_count = 0;
#endif /* __WIN__ */
/* Put to the list of events */
@@ -218,6 +219,7 @@ os_event_set(
/* Do nothing */
} else {
event->is_set = TRUE;
+ event->signal_count += 1;
ut_a(0 == pthread_cond_broadcast(&(event->cond_var)));
}
@@ -310,9 +312,15 @@ os_event_wait(
os_thread_exit(NULL);
}
#else
+ ib_longlong old_signal_count;
+
os_fast_mutex_lock(&(event->os_mutex));
+
+ old_signal_count = event->signal_count;
loop:
- if (event->is_set == TRUE) {
+ if (event->is_set == TRUE
+ || event->signal_count != old_signal_count) {
+
os_fast_mutex_unlock(&(event->os_mutex));
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
@@ -326,8 +334,9 @@ loop:
pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
- /* Solaris manual said that spurious wakeups may occur: we have
- to check the 'is_set' variable again */
+ /* Solaris manual said that spurious wakeups may occur: we have to
+ check if the event really has been signaled after we came here to
+ wait */
goto loop;
#endif
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index dc2a50c4f0c..af73c2f62c3 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -1655,7 +1655,7 @@ row_drop_table_for_mysql_in_background(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
+ log_buffer_flush_to_disk();
trx_commit_for_mysql(trx);
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index d13d499dd17..083cbfd2609 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -2836,7 +2836,7 @@ loop:
at transaction commit */
srv_main_thread_op_info = (char*)"flushing log";
- log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
+ log_buffer_flush_to_disk();
/* If there were less than 5 i/os during the
one second sleep, we assume that there is free
@@ -2852,10 +2852,9 @@ loop:
(char*)"doing insert buffer merge";
ibuf_contract_for_n_pages(TRUE, 5);
- srv_main_thread_op_info =
- (char*)"flushing log";
- log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP,
- TRUE);
+ srv_main_thread_op_info = (char*)"flushing log";
+
+ log_buffer_flush_to_disk();
}
if (buf_get_modified_ratio_pct() >
@@ -2905,7 +2904,7 @@ loop:
buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
srv_main_thread_op_info = (char*) "flushing log";
- log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
+ log_buffer_flush_to_disk();
}
/* We run a batch of insert buffer merge every 10 seconds,
@@ -2915,7 +2914,7 @@ loop:
ibuf_contract_for_n_pages(TRUE, 5);
srv_main_thread_op_info = (char*)"flushing log";
- log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
+ log_buffer_flush_to_disk();
/* We run a full purge every 10 seconds, even if the server
were active */
@@ -2939,8 +2938,7 @@ loop:
if (difftime(current_time, last_flush_time) > 1) {
srv_main_thread_op_info = (char*) "flushing log";
- log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP,
- TRUE);
+ log_buffer_flush_to_disk();
last_flush_time = current_time;
}
}
@@ -3060,6 +3058,10 @@ flush_loop:
(char*) "waiting for buffer pool flush to end";
buf_flush_wait_batch_end(BUF_FLUSH_LIST);
+ srv_main_thread_op_info = (char*) "flushing log";
+
+ log_buffer_flush_to_disk();
+
srv_main_thread_op_info = (char*)"making checkpoint";
log_checkpoint(TRUE, FALSE);
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 095a9df9082..0dead50264b 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -1524,6 +1524,8 @@ trx_commit_complete_for_mysql(
dulint lsn = trx->commit_lsn;
ut_a(trx);
+
+ trx->op_info = (char*)"flushing log";
if (srv_flush_log_at_trx_commit == 0) {
/* Do nothing */
@@ -1547,6 +1549,8 @@ trx_commit_complete_for_mysql(
ut_a(0);
}
+ trx->op_info = (char*)"";
+
return(0);
}
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 2cc64b18706..8edec984962 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -915,7 +915,7 @@ innobase_flush_logs(void)
DBUG_ENTER("innobase_flush_logs");
- log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
+ log_buffer_flush_to_disk();
DBUG_RETURN(result);
}
@@ -3538,7 +3538,7 @@ ha_innobase::create(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
+ log_buffer_flush_to_disk();
innobase_table = dict_table_get(norm_name, NULL);
@@ -3613,7 +3613,7 @@ ha_innobase::delete_table(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
+ log_buffer_flush_to_disk();
/* Tell the InnoDB server that there might be work for
utility threads: */
@@ -3683,7 +3683,7 @@ innobase_drop_database(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
+ log_buffer_flush_to_disk();
/* Tell the InnoDB server that there might be work for
utility threads: */
@@ -3755,7 +3755,7 @@ ha_innobase::rename_table(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
- log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
+ log_buffer_flush_to_disk();
/* Tell the InnoDB server that there might be work for
utility threads: */