summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
Diffstat (limited to 'innobase')
-rw-r--r--innobase/buf/buf0buf.c14
-rw-r--r--innobase/include/srv0start.h1
-rw-r--r--innobase/os/os0file.c28
-rw-r--r--innobase/row/row0sel.c21
-rw-r--r--innobase/srv/srv0start.c23
-rw-r--r--innobase/trx/trx0roll.c49
-rw-r--r--innobase/trx/trx0sys.c26
7 files changed, 129 insertions, 33 deletions
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index 3c6ec424434..14d538a14bc 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -346,13 +346,21 @@ buf_page_print(
ut_dulint_get_high(btr_page_get_index_id(read_buf)),
ut_dulint_get_low(btr_page_get_index_id(read_buf)));
- index = dict_index_find_on_id_low(
+ /* If the code is in ibbackup, dict_sys may be uninitialized,
+ i.e., NULL */
+
+ if (dict_sys != NULL) {
+
+ index = dict_index_find_on_id_low(
btr_page_get_index_id(read_buf));
- if (index) {
- fprintf(stderr, "InnoDB: and table %s index %s\n",
+ if (index) {
+ fprintf(stderr,
+ "InnoDB: and table %s index %s\n",
index->table_name,
index->name);
+ }
}
+
} else if (fil_page_get_type(read_buf) == FIL_PAGE_INODE) {
fprintf(stderr, "InnoDB: Page may be an 'inode' page\n");
} else if (fil_page_get_type(read_buf) == FIL_PAGE_IBUF_FREE_LIST) {
diff --git a/innobase/include/srv0start.h b/innobase/include/srv0start.h
index 24cdecb7341..aec3ebfeea9 100644
--- a/innobase/include/srv0start.h
+++ b/innobase/include/srv0start.h
@@ -81,6 +81,7 @@ innobase_shutdown_for_mysql(void);
extern ulint srv_sizeof_trx_t_in_ha_innodb_cc;
+extern ibool srv_is_being_started;
extern ibool srv_startup_is_before_trx_rollback_phase;
extern ibool srv_is_being_shut_down;
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 82ed957b5fb..5ffcabf6fe6 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -196,7 +196,7 @@ os_file_get_last_error(void)
err = (ulint) GetLastError();
- if (err != ERROR_FILE_EXISTS && err != ERROR_DISK_FULL) {
+ if (err != ERROR_DISK_FULL && err != ERROR_FILE_EXISTS) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Operating system error number %li in a file operation.\n"
@@ -220,6 +220,8 @@ os_file_get_last_error(void)
}
}
+ fflush(stderr);
+
if (err == ERROR_FILE_NOT_FOUND) {
return(OS_FILE_NOT_FOUND);
} else if (err == ERROR_DISK_FULL) {
@@ -232,7 +234,7 @@ os_file_get_last_error(void)
#else
err = (ulint) errno;
- if (err != EEXIST && err != ENOSPC ) {
+ if (err != ENOSPC && err != EEXIST) {
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -256,6 +258,8 @@ os_file_get_last_error(void)
}
}
+ fflush(stderr);
+
if (err == ENOSPC ) {
return(OS_FILE_DISK_FULL);
#ifdef POSIX_ASYNC_IO
@@ -278,7 +282,8 @@ static
ibool
os_file_handle_error(
/*=================*/
- /* out: TRUE if we should retry the operation */
+ /* out: TRUE if we should retry the
+ operation */
os_file_t file, /* in: file pointer */
char* name) /* in: name of a file or NULL */
{
@@ -308,12 +313,15 @@ os_file_handle_error(
os_has_said_disk_full = TRUE;
+ fflush(stderr);
+
return(FALSE);
} else if (err == OS_FILE_AIO_RESOURCES_RESERVED) {
return(TRUE);
} else if (err == OS_FILE_ALREADY_EXISTS) {
+
return(FALSE);
} else {
if (name) {
@@ -322,6 +330,8 @@ os_file_handle_error(
fprintf(stderr, "InnoDB: Cannot continue operation.\n");
+ fflush(stderr);
+
exit(1);
}
@@ -1063,7 +1073,17 @@ error_handling:
if (retry) {
goto try_again;
}
-
+
+ fprintf(stderr,
+"InnoDB: Fatal error: cannot read from file. OS error number %lu.\n",
+#ifdef __WIN__
+ (ulint)GetLastError()
+#else
+ (ulint)errno
+#endif
+ );
+ fflush(stderr);
+
ut_error;
return(FALSE);
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 1fc329fe2ca..fb508e7b1da 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2145,19 +2145,14 @@ row_sel_store_mysql_rec(
extern_field_heap = NULL;
}
} else {
- /* MySQL sometimes seems to copy the 'data'
- pointed to by a BLOB field even if the field
- has been marked to contain the SQL NULL value.
- This caused seg faults reported by two users.
- Set the BLOB length to 0 and the data pointer
- to NULL to avoid a seg fault. */
-
- if (templ->type == DATA_BLOB) {
- row_sel_field_store_in_mysql_format(
- mysql_rec + templ->mysql_col_offset,
- templ->mysql_col_len, NULL,
- 0, templ->type, templ->is_unsigned);
- }
+ /* MySQL seems to assume the field for an SQL NULL
+ value is set to zero. Not taking this into account
+ caused seg faults with NULL BLOB fields, and
+ bug number 154 in the MySQL bug database: GROUP BY
+ and DISTINCT could treat NULL values inequal. */
+
+ memset(mysql_rec + templ->mysql_col_offset, '\0',
+ templ->mysql_col_len);
if (!templ->mysql_null_bit_mask) {
fprintf(stderr,
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 671ef4e5b22..33d4a30e227 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -577,8 +577,11 @@ open_or_create_log_file(
|| 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);
+"InnoDB: Error: log file %s is of different size %lu %lu bytes\n"
+"InnoDB: than specified in the .cnf file %lu %lu bytes!\n",
+ name, size_high, size,
+ srv_calc_high32(srv_log_file_size),
+ srv_calc_low32(srv_log_file_size));
return(DB_ERROR);
}
@@ -770,8 +773,13 @@ open_or_create_data_files(
rounded_size_pages)) {
fprintf(stderr,
- "InnoDB: Error: data file %s is of a different size\n"
- "InnoDB: than specified in the .cnf file!\n", name);
+"InnoDB: Error: auto-extending data file %s is of a different size\n"
+"InnoDB: %lu pages (rounded down to MB) than specified in the .cnf file:\n"
+"InnoDB: initial %lu pages, max %lu (relevant if non-zero) pages!\n",
+ name, rounded_size_pages,
+ srv_data_file_sizes[i], srv_last_file_size_max);
+
+ return(DB_ERROR);
}
srv_data_file_sizes[i] =
@@ -782,8 +790,11 @@ open_or_create_data_files(
!= srv_data_file_sizes[i]) {
fprintf(stderr,
- "InnoDB: Error: data file %s is of a different size\n"
- "InnoDB: than specified in the .cnf file!\n", name);
+"InnoDB: Error: data file %s is of a different size\n"
+"InnoDB: %lu pages (rounded down to MB)\n"
+"InnoDB: than specified in the .cnf file %lu pages!\n", name,
+ rounded_size_pages,
+ srv_data_file_sizes[i]);
return(DB_ERROR);
}
diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c
index 1f0e0c58ac7..a9f8c5ad22c 100644
--- a/innobase/trx/trx0roll.c
+++ b/innobase/trx/trx0roll.c
@@ -21,6 +21,7 @@ Created 3/26/1996 Heikki Tuuri
#include "que0que.h"
#include "usr0sess.h"
#include "srv0que.h"
+#include "srv0start.h"
#include "row0undo.h"
#include "row0mysql.h"
#include "lock0lock.h"
@@ -29,6 +30,12 @@ Created 3/26/1996 Heikki Tuuri
/* This many pages must be undone before a truncate is tried within rollback */
#define TRX_ROLL_TRUNC_THRESHOLD 1
+/* In crash recovery we set this to the undo n:o of the current trx to be
+rolled back. Then we can print how many % the rollback has progressed. */
+ib_longlong trx_roll_max_undo_no;
+/* Auxiliary variable which tells the previous progress % we printed */
+ulint trx_roll_progress_printed_pct;
+
/***********************************************************************
Rollback a transaction used in MySQL. */
@@ -174,6 +181,8 @@ trx_rollback_or_clean_all_without_sess(void)
roll_node_t* roll_node;
trx_t* trx;
dict_table_t* table;
+ ib_longlong rows_to_undo;
+ char* unit = (char*)"";
int err;
mutex_enter(&kernel_mutex);
@@ -219,8 +228,7 @@ loop:
trx->sess = trx_dummy_sess;
- if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) {
-
+ if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) {
fprintf(stderr, "InnoDB: Cleaning up trx with id %lu %lu\n",
ut_dulint_get_high(trx->id),
ut_dulint_get_low(trx->id));
@@ -248,9 +256,19 @@ loop:
ut_a(thr == que_fork_start_command(fork, SESS_COMM_EXECUTE, 0));
- fprintf(stderr, "InnoDB: Rolling back trx with id %lu %lu\n",
+ trx_roll_max_undo_no = ut_conv_dulint_to_longlong(trx->undo_no);
+ trx_roll_progress_printed_pct = 0;
+ rows_to_undo = trx_roll_max_undo_no;
+ if (rows_to_undo > 1000000000) {
+ rows_to_undo = rows_to_undo / 1000000;
+ unit = (char*)"M";
+ }
+
+ fprintf(stderr,
+"InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo",
ut_dulint_get_high(trx->id),
- ut_dulint_get_low(trx->id));
+ ut_dulint_get_low(trx->id),
+ (ulint)rows_to_undo, unit);
mutex_exit(&kernel_mutex);
if (trx->dict_operation) {
@@ -300,7 +318,7 @@ loop:
row_mysql_unlock_data_dictionary(trx);
}
- fprintf(stderr, "InnoDB: Rolling back of trx id %lu %lu completed\n",
+ fprintf(stderr, "\nInnoDB: Rolling back of trx id %lu %lu completed\n",
ut_dulint_get_high(trx->id),
ut_dulint_get_low(trx->id));
mem_heap_free(heap);
@@ -614,6 +632,7 @@ trx_roll_pop_top_rec_of_trx(
dulint undo_no;
ibool is_insert;
trx_rseg_t* rseg;
+ ulint progress_pct;
mtr_t mtr;
rseg = trx->rseg;
@@ -676,6 +695,26 @@ try_again:
ut_ad(ut_dulint_cmp(ut_dulint_add(undo_no, 1), trx->undo_no) == 0);
+ /* We print rollback progress info if we are in a crash recovery
+ and the transaction has at least 1000 row operations to undo */
+
+ if (srv_is_being_started && trx_roll_max_undo_no > 1000) {
+ progress_pct = 100 - (ulint)
+ ((ut_conv_dulint_to_longlong(undo_no) * 100)
+ / trx_roll_max_undo_no);
+ if (progress_pct != trx_roll_progress_printed_pct) {
+ if (trx_roll_progress_printed_pct == 0) {
+ fprintf(stderr,
+ "\nInnoDB: Progress in percents: %lu", progress_pct);
+ } else {
+ fprintf(stderr,
+ " %lu", progress_pct);
+ }
+ fflush(stderr);
+ trx_roll_progress_printed_pct = progress_pct;
+ }
+ }
+
trx->undo_no = undo_no;
if (!trx_undo_arr_store_info(trx, undo_no)) {
diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
index 33c962772e8..1ae9f00ae1f 100644
--- a/innobase/trx/trx0sys.c
+++ b/innobase/trx/trx0sys.c
@@ -699,6 +699,9 @@ trx_sys_init_at_db_start(void)
/*==========================*/
{
trx_sysf_t* sys_header;
+ ib_longlong rows_to_undo = 0;
+ char* unit = (char*)"";
+ trx_t* trx;
mtr_t mtr;
mtr_start(&mtr);
@@ -734,9 +737,28 @@ trx_sys_init_at_db_start(void)
trx_lists_init_at_db_start();
if (UT_LIST_GET_LEN(trx_sys->trx_list) > 0) {
+ trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
+
+ for (;;) {
+ rows_to_undo +=
+ ut_conv_dulint_to_longlong(trx->undo_no);
+ trx = UT_LIST_GET_NEXT(trx_list, trx);
+
+ if (!trx) {
+ break;
+ }
+ }
+
+ if (rows_to_undo > 1000000000) {
+ unit = (char*)"M";
+ rows_to_undo = rows_to_undo / 1000000;
+ }
+
fprintf(stderr,
- "InnoDB: %lu transaction(s) which must be rolled back or cleaned up\n",
- UT_LIST_GET_LEN(trx_sys->trx_list));
+"InnoDB: %lu transaction(s) which must be rolled back or cleaned up\n"
+"InnoDB: in total %lu%s row operations to undo\n",
+ UT_LIST_GET_LEN(trx_sys->trx_list),
+ (ulint)rows_to_undo, unit);
fprintf(stderr, "InnoDB: Trx id counter is %lu %lu\n",
ut_dulint_get_high(trx_sys->max_trx_id),